The CSS Cascade
The cascade is the algorithm that determines which CSS rule wins when multiple rules apply to the same element. It evaluates rules in order of priority.
Priority order (highest to lowest)
- Origin and importance - where the style comes from and whether it is
!important - Context - styles inside a shadow DOM vs outside
- Inline styles - the
styleattribute - Cascade layers - order of
@layerblocks (for!importantthe order is reversed) - Specificity - how specific the selector is
- Source order - which rule comes last
1 - Importance
css
.btn { color: blue !important; } /* wins over everything */
#btn { color: red; } /* loses */1 - Origin
text
Browser !important
> User !important
> Author !important (your CSS)
> Author styles
> User preferences
> Browser defaults2 - Cascade layers
css
@layer base, components;
@layer base { .btn { color: gray; } }
@layer components { button { color: blue; } } /* wins despite lower specificity */3 - Specificity
css
#id .class a { color: red; } /* (1,1,1) */
.nav a { color: blue; } /* (0,1,1) */
/* red wins */4 - Source order
css
.btn { color: red; }
.btn { color: blue; } /* wins - comes later */Inheritance
Some properties (text-related) are inherited from parent to child automatically.
css
body { font-family: sans-serif; color: #333; }
/* all text elements inherit these unless overridden */Non-inherited properties (box model, positioning) do not cascade down.
css
/* force inherit or reset */
.child { color: inherit; }
.child { color: initial; } /* browser default */
.child { color: unset; } /* inherited if inheritable, else initial */Understanding the cascade helps you avoid specificity wars. Modern best practices favor low-specificity selectors (class-only,
:where()) and@layerto order resets, libraries and components explicitly.
updated
did you know it?