You add a CSS rule. The element ignores it. You add !important and it works, but now something else breaks. You've been in a specificity battle — and you lost because you didn't know the rules. CSS specificity is the algorithm the browser uses to decide which declaration wins when multiple rules target the same property on the same element. Once you understand it, the logic is completely deterministic — no more guessing.
The DevToolShack CSS Specificity Calculator shows you the specificity score of any selector instantly. Paste your selectors and see which one wins.
The Specificity Score: (A, B, C)
Every selector gets a three-number score: (A, B, C). Higher scores win. Scores are compared left to right — A beats any number of B, B beats any number of C.
| Selector Type | Increments | Example |
|---|---|---|
| Inline styles | A | style="color: red" |
| ID selectors | A | #header |
| Class selectors | B | .btn |
| Attribute selectors | B | [type="text"] |
| Pseudo-classes | B | :hover, :nth-child() |
| Type selectors | C | div, p, button |
| Pseudo-elements | C | ::before, ::after |
| Universal selector | Nothing | * |
| Combinators | Nothing | >, +, ~, space |
Calculating Specificity
/* (0, 0, 1) — one type selector */
p { color: blue; }
/* (0, 1, 0) — one class selector */
.text { color: green; }
/* (0, 1, 1) — one class + one type */
p.text { color: orange; }
/* (1, 0, 0) — one ID selector */
#intro { color: red; }
/* (1, 1, 1) — one ID + one class + one type */
#intro p.text { color: purple; }
When two rules target the same element with the same property, the one with the higher score wins. If scores are equal, the rule that appears later in the stylesheet wins — source order.
Real-World Examples
/* (0, 0, 1) */
a { color: blue; }
/* (0, 1, 0) — wins over the above */
.nav-link { color: white; }
/* (0, 1, 1) — wins over both */
nav a { color: white; } /* wait — this is (0,0,2), not (0,1,1) */
nav .nav-link { color: white; } /* this IS (0,1,1) — wins */
/* (1, 0, 0) — beats everything above */
#main-nav a { color: yellow; }
(0, 1, 0) always beats (0, 0, 100). One class beats any number of type selectors. One ID beats any number of classes. Don't add up the numbers across columns.!important: The Override Nuclear Option
!important overrides all specificity — but creates its own problems. Once you use it, the only way to override it is with another !important of equal or higher specificity. This quickly escalates into specificity wars.
/* Avoid this pattern — it creates technical debt */
.button { color: blue !important; }
.button-red { color: red !important; } /* fights the previous !important */
Legitimate uses for !important are rare: utility classes that must always win (.hidden { display: none !important; }), and overriding third-party styles you can't edit.
Specificity Best Practices
Keep specificity low and flat
The lower and more consistent your specificity, the easier your CSS is to maintain. Aim for mostly class-level specificity (0, 1, 0) throughout your stylesheet — avoid ID selectors in CSS, avoid deeply nested selectors, and avoid inline styles.
/* ❌ High specificity — hard to override later */
#sidebar .widget ul li a { color: blue; }
/* ✅ Low specificity — easy to work with */
.sidebar-link { color: blue; }
Use :where() to write zero-specificity selectors
The :where() pseudo-class matches the same elements as its argument, but contributes zero specificity. Useful for base styles and resets that you want overrideable by anything:
/* Zero specificity — any class or ID can override this */
:where(h1, h2, h3, h4, h5, h6) {
line-height: 1.2;
margin-top: 0;
}
:is() and :not() carry the specificity of their most specific argument
/* Specificity of (1,0,0) — because #id is in the list */
:is(#id, .class, div) { color: blue; }
/* Specificity of (0,1,0) — .class is the most specific */
:is(.class, span) { color: blue; }
!important. The Specificity Calculator shows you the exact score of any selector and which one wins in a comparison. Pair it with the CSS Formatter to clean up your stylesheet while you're at it.