CSS specificity is the scoring system the browser uses to decide which rule wins when two selectors style the same element. If your rule “is not applying,” another selector almost certainly has a higher score. Here is how that score works and how to count it.
How CSS specificity is scored
Think of specificity as a tuple of four numbers, compared left to right:
(inline, IDs, classes/attributes/pseudo-classes, elements/pseudo-elements)
- Inline styles (
style="..."on the element) add to the first slot. - ID selectors (
#nav) add to the second slot. - Classes (
.item), attribute selectors ([type="text"]), and pseudo-classes (:hover,:nth-child) add to the third slot. - Type selectors (
div,a) and pseudo-elements (::before) add to the fourth slot.
The browser compares the tuples position by position. A selector with one ID beats any number of classes, because the ID slot is checked before the class slot. So (0,1,0,0) always wins over (0,0,9,0). Higher specificity wins regardless of where the rules sit in your stylesheet.
The universal selector (*) and combinators (>, +, ~) add nothing. The :where() pseudo-class also contributes zero specificity, no matter what you put inside it, which makes it perfect for low-priority base styles. Its sibling :is() is different: it takes the specificity of its most specific argument.
A worked example: #nav .item vs .item
Say you have these two rules:
#nav .item { color: red; } /* (0,1,1,0) */
.item { color: blue; } /* (0,0,1,0) */
The first selector has one ID and one class, scoring (0,1,1,0). The second has one class, scoring (0,0,1,0). The ID slot decides it before the class slot is even compared, so the text is red, even if the blue rule appears later in the file. To make blue win, you would have to match or beat that ID, for example by raising the second selector to #nav .item.active.
What about source order and !important
Source order only matters on a tie. When two selectors have the exact same specificity, the one declared last wins. That is the only time “later in the file” helps you, so reordering rules will not fix a genuine specificity mismatch.
!important overrides normal specificity entirely and should be a last resort. It pulls the declaration into a separate, higher layer that ignores the tuple, which means the only way to beat it is another !important with higher specificity. That escalation is how stylesheets become unmaintainable. Inline styles sit just below !important: they beat any selector but lose to an !important declaration. Reach for clearer selectors first.
Count any selector instantly
When a selector’s score is not obvious, do not guess:
- Open the CSS Specificity Calculator.
- Paste the selector that is winning and the one that is losing.
- Compare the two tuples side by side to see exactly which slot is deciding it.
- Adjust the weaker selector until it matches or beats the other.
The CSS Specificity Calculator runs entirely in your browser, so nothing you paste leaves your device.
Related tools
- Shipping the final CSS? Shrink it with the CSS Minifier.
- Building backgrounds? Try the CSS Gradient Generator.
- Need exact color values? Check the Tailwind Color Reference.
Count the tuple, beat it on the right slot, and leave !important out of it.