CSS Specificity Calculator
Paste up to three selectors. See which one wins the cascade and why.
Selector A
Selector B
Selector C
How specificity is calculated
ID selectors
Each #id in your selector adds 1 to the first number. A single ID outweighs any number of classes or elements. This is why ID-heavy selectors are hard to override.
Classes, attributes, pseudo-classes
Each .class, [attr], or :pseudo-class adds 1 to the second number. This group includes :hover, :focus, :nth-child(), and :not() (which takes the specificity of its most specific argument).
Elements and pseudo-elements
Each element name or ::pseudo-element adds 1 to the third number. Type selectors like div, p, and h1 live here. So do ::before and ::after.
See it in action
Imagine this HTML structure:
<nav id="main-nav" class="top">
<a href="/" class="link active">Home</a>
</nav>
Now compare two rules targeting that link:
.top .link.active { color: blue; }
(0, 3, 0)
#main-nav a.link { color: red; }
(1, 1, 1)
The second rule wins. Even though its total (3) equals the first rule's total (3), specificity compares left to right. The ID in position one beats zero IDs. The color will be red.
Common specificity pitfalls
Stacking classes to beat an ID
You cannot beat (1,0,0) with any number of classes. .a.b.c.d.e.f.g scores (0,7,0) and still loses to #x. If you need to override an ID, add an ID of your own, use :where() to lower the original, or restructure your CSS.
:is() and :not() take their highest argument
:is(#main, .link) contributes (1,0,0) to the score, not (0,1,0). Many developers assume :is() averages or sums its contents. It does not. It uses the most specific selector inside the parentheses.
:where() always scores zero
:where(#sidebar .widget a) adds nothing to specificity. This is intentional. Use :where() for reset styles or design-token overrides that should be easy to replace without fighting the cascade.
The universal selector and combinators score zero
*, >, +, ~, and a space (descendant combinator) do not add to specificity. ul > li + li scores (0,0,3) for the three element names only.
Inline styles beat everything except !important
An inline style attribute scores higher than any author stylesheet selector. SpeciLab does not parse inline styles in the input, but remember they occupy a fourth, hidden position in the specificity tuple: (inline, ID, class, element).
@layer can override normal specificity
Cascade layers change the game. A lower-specificity selector in a later layer beats a higher-specificity selector in an earlier layer. SpeciLab scores standard specificity only. If you use @layer, the winner may differ from what the calculator shows.
Resolution strategies ranked by maintainability
- Use classes for everything. Flat class-based selectors like
.nav-link-activeare easy to override and reason about. This is the single most effective habit. - Use :where() to lower specificity. Wrap a third-party or legacy selector in
:where()so your override needs less weight. - Scope with a parent class. Adding
.theme-darkbefore a selector gives you (0,1,0) of extra weight without reaching for an ID. - Use an extra class instead of an ID. Replace
#sidebarwith.sidebarif you do not need the uniqueness guarantee of an ID. - Duplicate a selector. Writing
.btn.btngives you (0,2,0) from a single class repeated. It is a small trick that avoids !important. - Use !important as a last resort. It breaks the normal cascade and makes future overrides harder. Reserve it for utility classes and overrides you truly never want beaten.
Why SpeciLab exists
CSS specificity is one of those topics that looks simple until three rules collide and the wrong one wins. Most calculators stop at showing a number. SpeciLab breaks that number apart so you can see exactly which part of your selector is doing the heavy lifting. It is built for front-end developers and students who want to stop guessing and start understanding the cascade.
Everything runs in your browser. No selectors are sent to any server. Your saved patterns stay in local storage on your device.
SpeciLab v1.1.0 · Updated 2026