Specificity & The Cascade
18 min read
SpecificityCascadeInheritance!important:where():is()Selector Weight
How the Browser Decides Which Rule Wins
When multiple CSS rules target the same element, the browser needs a tiebreaker system. This system is called The Cascade, and it follows a strict priority order.
The Cascade Priority (Highest to Lowest)
| Priority | Source | Example |
|---|---|---|
| 1 (Highest) | !important declarations | color: red !important; |
| 2 | Inline styles | <p style="color: blue"> |
| 3 | ID selectors | #header { color: green; } |
| 4 | Class / Attribute / Pseudo-class | .nav { color: orange; } |
| 5 | Element / Pseudo-element | p { color: black; } |
| 6 (Lowest) | Universal selector | * { color: gray; } |
Calculating Specificity
Specificity is calculated as a tuple: (Inline, IDs, Classes, Elements)
| Selector | Specificity | Score |
|---|---|---|
p | (0, 0, 0, 1) | 1 |
.card | (0, 0, 1, 0) | 10 |
#main | (0, 1, 0, 0) | 100 |
#main .card p | (0, 1, 1, 1) | 111 |
style="..." | (1, 0, 0, 0) | 1000 |
.card.active:hover | (0, 0, 3, 0) | 30 |
Inheritance
Some CSS properties are inherited by child elements, others are not:
| Inherited ✅ | NOT Inherited ❌ |
|---|---|
color | border |
font-family | padding |
font-size | margin |
line-height | width / height |
visibility | background |
cursor | display |
Use inherit, initial, or unset to control inheritance explicitly.
The :where() and :is() Difference
:is() takes the specificity of its most specific argument. :where() always has zero specificity, making it perfect for resets and defaults that should be easily overridable.