The Cascade in Depth
The full cascade sorts competing declarations by these criteria, in order. The first one that differs decides:
- Origin and importance
- Context (shadow DOM: outer tree vs inner tree)
- Element-attached styles (
style="...") - Cascade layers
- Specificity
- Scope proximity (
@scope) - Order of appearance
Origins
There are three main origins:
- User-agent — the browser's default styles (why
h1is big and links are blue). - User — styles the visitor sets (some browsers and extensions allow a custom stylesheet, e.g. larger fonts or high contrast).
- Author — your stylesheets.
For normal declarations the order of precedence is user-agent < user
< author. For !important declarations it reverses: author
important < user important < user-agent important. That's deliberate: a
user's !important accessibility styles beat anything a site does.
Animations and transitions also have their own places in this order: running animations override normal declarations, and transitions override even important ones while they run.
The global keywords, precisely
<style>
.parent { color: rgb(200, 0, 0); }
.a { color: inherit; }
.b { color: initial; }
.c { color: unset; }
.d { color: revert; }
.e { display: revert; }
.f { display: initial; }
</style>
<div class="parent">
<p class="a">a</p><p class="b">b</p><p class="c">c</p><p class="d">d</p><p class="e">e</p><p class="f">f</p>
</div>
<script>
for (const p of document.querySelectorAll(".parent p")) {
const s = getComputedStyle(p);
console.log(p.className, s.color, s.display);
}
</script>
a rgb(200, 0, 0) block
b rgb(0, 0, 0) block
c rgb(200, 0, 0) block
d rgb(200, 0, 0) block
e rgb(200, 0, 0) block
f rgb(200, 0, 0) inline
inherittook the parent's red;unsetdid the same, becausecoloris an inherited property.initialgavecolor's initial value (canvastext, black here).revertrolled back to the previous origin — forcolorthere is no browser rule forp, so it inherited red; fordisplaythe browser'sp { display: block }came back.display: initialisinline— the spec's initial value, not the browser default forp. This is whyinitialis rarely what you want.revert-layerrolls back to the previous cascade layer (next lesson).
Why this matters in practice
all: reverton an element removes every author style — handy inside components that must not inherit site styles.- Inline
styleattributes beat any selector (step 3), but not!importantdeclarations in a stylesheet (step 1). - Specificity doesn't matter across layers — step 4 comes first. That's the key to the next lesson.