Cascade & Specificity
How CSS decides the winner — origin, importance, layers, specificity, and order — in human terms.
- css
- cascade
- specificity
When two declarations target the same property on the same element, the cascade picks one. Specificity is a step in that fight — not the whole rulebook.
If your debugging strategy is “add classes until it works, then !important,” this is the reset button.
Order of battle (simplified, author styles)
- Cascade layers (
@layer) — later layers beat earlier ones for normal declarations - Specificity of the selector
- Source order — last tied rule wins
- Inline styles sit high on the specificity ladder
!importantflips a lot of origin/layer rules — treat it as a last resort
User-agent and user styles also participate; most app work is author CSS.
Specificity as a scoreboard
Rough tuple: (inline, IDs, classes/attributes/pseudo-classes, elements/pseudo-elements).
| Selector | Rough weight |
|---|---|
div |
elements |
.card |
one class |
.card.featured |
two classes |
#hero |
one ID |
button:hover |
class-ish + element |
.nav a { color: blue; } /* class + element */
a.nav-link { color: red; } /* same ballpark — later wins if equal */
:where() contributes zero specificity — great for base styles you want to override easily.
:is() takes the most specific argument inside it — easy footgun with IDs.
Layers beat selector wars
@layer reset, base, components, utilities;
@layer components {
.button { color: white; }
}
@layer utilities {
.text-accent { color: var(--accent); }
}
A utility in a later layer can win even with a lighter selector. That’s how design systems stay sane.
Inheritance ≠ cascade
- Cascade chooses among declarations for a property.
- Inheritance fills inheritable properties (
color,font-*, …) when nothing was declared.
margin does not inherit. color does. inherit / initial / unset / revert are the explicit controls.
Habits that age well
- Prefer boring class selectors
- Reach for layers before escalating specificity
- Avoid IDs in app CSS
- Reserve
!importantfor rare utilities or third-party overrides - Theme with custom properties instead of selector cage matches
Debug checklist (DevTools)
- Is the property applied at all?
- Which rule is struck through?
- Layer or
!importantinvolved? - Did a later file silently win?
Further reading
Related
Related guides
- CSS Masks and Clip PathCSS Masks and Clip Path explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- CSS Box ModelCSS Box Model explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- Print StylesheetsPrint Stylesheets explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- box-sizing border-boxbox-sizing border-box explained for frontend engineers — mental model, examples, common mistakes, and interview tips.
- prefers-reduced-motionprefers-reduced-motion explained for frontend engineers — mental model, examples, common mistakes, and interview tips.