CSS: Specificity & Cascade
Understand how the browser decides which CSS rule wins.
How Specificity is Calculated
Specificity is a score the browser assigns to every CSS rule. When two rules target the same element and set the same property, the rule with the higher specificity score wins.
The score is written as three numbers: (A, B, C) where:
- A: number of ID selectors in the rule
- B: number of class, attribute, and pseudo-class selectors
- C: number of element (type) and pseudo-element selectors
Specificity Score (A, B, C)
Compare scores left to right. A higher A beats any B or C value. Inline styles sit above all three.
- p { }score (0, 0, 1): one element selector
- .card { }score (0, 1, 0): one class selector
- #header { }score (1, 0, 0): one ID selector
- div.card p { }score (0, 1, 2): one class + two elements
- Inline style='...' : score (1, 0, 0, 0), beats everything except !important
Specificity Score Demo
The highest specificity score determines the winning rule.
p { color: gray; } /* (0,0,1) */
.highlight { color: green; } /* (0,1,0) */
#title { color: crimson; } /* (1,0,0) wins */Specificity Hierarchy
From lowest to highest, the four levels of specificity are:
| Level | Selector Type | Score | Example |
|---|---|---|---|
| 1: Lowest | Element / pseudo-element | (0,0,1) | p, h1, ::before |
| 2 | Class / attribute / pseudo-class | (0,1,0) | .card, [type], :hover |
| 3 | ID selector | (1,0,0) | #header, #nav |
| 4: Highest | Inline style | (1,0,0,0) | style='color:red' |
Specificity Hierarchy
Think of it as a 4-digit number. Inline styles are the thousands digit, IDs are hundreds, classes are tens, and elements are ones. A higher digit always beats a lower one.
- Inline stylesbeat all stylesheet rules
- ID selectorsbeat class and element selectors
- Class selectorsbeat element selectors
- Element selectorslowest specificity, easiest to override
- The universal selector * has zero specificity (0,0,0)
Specificity Hierarchy
Inline style beats ID, which beats class, which beats element.
h1 { color: gray; } /* (0,0,1) element */
.title { color: green; } /* (0,1,0) class */
#main { color: blue; } /* (1,0,0) ID */
/* style="color:orange" wins inline style */The Cascade Rules
The cascade is the algorithm the browser uses to decide which CSS rule applies when multiple rules target the same element. It considers three things in order:
- Origin, where does the style come from? (browser defaults, author stylesheet, user stylesheet)
- Specificity, which rule has the higher score?
- Source order, if specificity is equal, the last rule written wins
The Cascade
The cascade resolves conflicts between CSS rules. It checks origin first, then specificity, then source order, stopping as soon as a winner is found.
- Originauthor styles override browser defaults; !important reverses this
- Specificityhigher score always wins regardless of order
- Source orderwhen scores are equal, the last declared rule wins
- Understanding the cascade helps you avoid writing unnecessary overrides
The Cascade
Specificity beats source order. Source order breaks ties.
.note { color: green; } /* (0,1,0) wins (higher specificity) */
p { color: red; } /* (0,0,1) loses despite coming second */Inheritance
Some CSS properties are inherited, child elements automatically receive the value from their parent without needing the rule repeated. Others are not inherited and must be set explicitly on each element.
Inheritance
Inherited properties flow down the DOM tree from parent to child automatically. Non-inherited properties reset to their initial value on each element.
- Inheritedcolor, font-family, font-size, line-height, text-align, visibility
- Not inheritedmargin, padding, border, background, width, height, display
- inheritkeyword that forces any property to inherit from its parent
- initialkeyword that resets a property to its browser default
Inheritance
Children inherit color and font-family from the parent.
.parent {
color: steelblue;
font-family: Georgia, serif;
/* border and padding are NOT inherited by children */
border: 1px solid steelblue;
padding: 12px;
}!important and When to Avoid It
Adding !important to a declaration forces it to win over all other rules regardless of specificity or source order.
!important
!important overrides the normal cascade completely. It should be avoided in almost all situations because it makes CSS hard to debug and maintain.
- color: red !important;wins over any other color declaration on that element
- Two !important rules fight each other, then specificity applies between them
- Legitimate uses: utility classes, accessibility overrides, third-party stylesheet overrides
- Never use it to fix a specificity problem, fix the selector instead
!important
!important overrides even an ID selector.
#msg { color: crimson; } /* (1,0,0) normally wins */
.note { color: green !important; } /* wins, !important beats everything */Source Order Importance
When two rules have exactly the same specificity, the one that appears last in the stylesheet wins. This is called source order.
Source Order
Source order is the tiebreaker when specificity scores are equal. The last rule declared in the stylesheet takes effect.
- Rules are read top to bottom, later rules override earlier ones of equal specificity
- @importimported stylesheets are treated as if they were pasted at that position
- This is why the order of your CSS rules and file links matters
- Always link your own stylesheet after third-party stylesheets so your rules win
Source Order
Two equal-specificity rules, the last one wins.
.note { color: red; } /* (0,1,0) declared first */
.note { color: blue; } /* (0,1,0) declared last, wins */Specificity Best Practices
Keeping specificity low and consistent makes your CSS easier to override, debug, and maintain.
Specificity Best Practices
Well-managed specificity means you rarely need to fight your own CSS. Follow these rules to keep your stylesheet predictable.
- Prefer class selectors over ID selectors for styling
- Avoid nesting selectors deeper than two levels, it raises specificity unnecessarily
- Never use !important to fix a specificity conflict, refactor the selector instead
- Keep utility classes as single-class rules so they remain easy to override
- Use low-specificity selectors at the top and increase specificity only when needed
Specificity Best Practices
Low-specificity class selectors that are easy to override.
/* Low specificity, easy to override */
.nav-link {
color: gray;
text-decoration: none;
}
/* One level higher, active state */
.nav-link.active {
color: steelblue;
font-weight: bold;
}Knowledge Check
1. Which selector has the highest specificity?
2. What is the specificity score of `div.card p`?
3. Which CSS property value overrides all other rules including higher specificity?
4. Which property is inherited by default?
5. When two rules have equal specificity, which one wins?