What the cascade actually is
An algorithm with numbered steps that runs on every declaration. Specificity is step three. Most people think it is the whole thing, so they lose arguments with their own stylesheets.
When two declarations both want to set color on the same element, the browser does not guess and does not take the last one it saw. It runs an algorithm, in a fixed order, and the first step that separates the two wins. Knowing the order is the useful part, because it tells you which question to ask when a rule does not apply.
Step one is origin and importance. There are three origins, the browser’s own stylesheet, the user’s, and yours, and each has a normal and an important band. The full order runs: browser normal, user normal, author normal, author important, user important, browser important. Notice the reversal: important declarations invert the usual precedence, so a user stylesheet forcing large text can override anything you write, by design, because accessibility beats art direction.
Step two is layers. @layer lets you declare bands of precedence up front, @layer reset, base, components, utilities;, and a declaration in a later layer beats one in an earlier layer no matter how specific the earlier one is. Unlayered styles beat all layers. This is the tool that makes third-party CSS manageable, and we come back to it in two chapters.
Step three is specificity, and only now. Three numbers: ids, then classes and attributes and pseudo-classes, then elements and pseudo-elements. Compared left to right, no carrying, a thousand classes never add up to one id.
Step four, if everything above ties, is source order. The last one written wins. Which sounds trivial until you remember that "last" in a bundled application means whatever order your build tool happened to concatenate files in, so two developers can see different results from the same code.
Inline styles sit between author normal and author important, above every normal author rule, below every important one. So the sentence "inline styles always win" is false, and the resolver below will show you exactly where it breaks.
Six declarations, one colour
Declarations: click to switch one off
- 1Origin and importance
important author > normal author > normal user-agent
- 2Layers and the style attribute
style attribute > unlayered > later layers > earlier layers
- 3Specificity
compare a, then b, then c: first difference decides
- 4Order of appearance
the last one written wins
Read the docs
computed color: not resolved yet
Six declarations, all setting color on the same element. Step through and watch the order the browser actually uses: the tie-breaker you remember is the third one it reaches.
Work the resolver in step mode. Toggle declarations on and off and watch which step does the eliminating. The habit to build is this: when a rule does not apply, do not immediately add a class or an !important. Ask which step is losing it. Nine times out of ten the answer is visible in DevTools, where the Styles panel shows overridden declarations struck through, and hovering the one that won tells you why.
Worth reading
- web.dev: The cascade ↗, The written reference, with the origin table laid out properly.
You should now be able to
- State the steps of the cascade in order
- Explain why an inline style can lose
- Say what !important actually does to the ordering
- Debug a rule that did not apply without guessing
Loading…