CSS Tutorial · Beyond the Basics · Lesson 16 of 19
CSS Cascade and Specificity
How the browser decides which rule wins.
When rules conflict
Several rules can target the same element. The browser picks the winner in this order:
- Importance —
!importantbeats normal declarations (avoid it). - Specificity — the more specific selector wins.
- Source order — if specificity is equal, the later rule wins.
Specificity
Count selectors as (id, class, type):
| Selector | Specificity |
|---|---|
p |
(0, 0, 1) |
.note, [type], :hover |
(0, 1, 0) |
p.note |
(0, 1, 1) |
#intro |
(1, 0, 0) |
inline style="" |
beats all selectors |
<style>
body { font: 15px system-ui; color: #334155; } /* inherited by everything */
p { color: #16a34a; } /* (0,0,1) */
.note { color: #2563eb; } /* (0,1,0) beats p */
p.note { color: #7c3aed; } /* (0,1,1) beats .note */
#special { color: #dc2626; } /* (1,0,0) beats classes */
.late { color: #ea580c; }
.late { color: #0891b2; } /* same specificity: last one wins */
</style>
<p>Type selector: green</p>
<p class="note">p.note: purple</p>
<p class="note" id="special">id selector: red</p>
<p class="late">Later rule wins: cyan</p>
<span>Inherited body colour</span>
Inheritance
Some properties — mostly text ones like color, font-family, line-height — are inherited by children. Others like margin, border and background are not.
Keep specificity low and flat (single classes), and you'll rarely fight the cascade. :where() has zero specificity, handy for defaults.
Test yourself
Which selector is most specific?
.nav a#navnav ul li aa:hover
Show answer
Answer: #nav