CSS Cascade
By Flavio
Learn what the CSS cascade is: the algorithm that decides which rules win for each element based on specificity, importance, inheritance and order in the file.
Cascade is a fundamental concept of CSS. After all, it’s in the name itself, the first C of CSS - Cascading Style Sheets - it must be an important thing.
What does it mean?
Cascade is the process, or algorithm, that determines the properties applied to each element on the page.
Trying to converge from a list of CSS rules that are defined in various places.
The cascade sorts competing declarations in this order:
- origin and importance
- context (shadow DOM)
- element-attached styles (the
styleattribute) - cascade layers
- specificity
- order of appearance
Inheritance is not a cascade step. It fills in a value only when nothing cascaded for that property.
It also takes care of resolving conflicts.
Two or more competing CSS rules for the same property applied to the same element need to be elaborated according to the CSS spec, to determine which one needs to be applied.
Even if you just have one CSS file loaded by your page, there is other CSS that is going to be part of the process. Origin is the first cascade step.
The browser (user agent) stylesheet comes first. Then the user stylesheet, which might also come from a browser extension. Then your author stylesheet.
For normal declarations, author beats user, and user beats the user agent. For !important declarations the order flips: user !important beats author !important.
All those rules come into play while rendering the page.
Two rules, one property
The algorithm is easier to see with two rules that target the same element.
p {
color: black;
}
.lead {
color: blue;
}
<p class="lead">Hello</p>
The paragraph is blue. Both rules set color. .lead wins because it is more specific than p.
If the two selectors have the same specificity, the last one in the file wins:
.lead {
color: blue;
}
.lead {
color: red;
}
The paragraph is red. Same class, same weight, later rule.
A style="color: green" attribute on the tag beats both of those. The style attribute sits above layers and specificity. An !important in your stylesheet still beats a normal style attribute.
Cascade layers
@layer lets you put rules into named buckets. Rules in an earlier-declared layer lose to later layers, no matter how specific they are. Unlayered styles beat layered ones. For !important declarations the layer order is reversed.
@layer reset, components;
@layer components {
.button {
color: blue;
}
}
@layer reset {
button {
color: black;
}
}
.button stays blue. The components layer is declared after reset, so it wins even though button is an element selector and .button is a class.
That is the point of layers. Put a reset in an early layer. Then a simple class in a later layer, or an unlayered rule, can override it. You do not have to raise specificity to win.
Be careful with unlayered CSS you add later. It beats every layered rule, even a very specific one. If a reset suddenly “does not apply”, look for an unlayered rule, not for a specificity bug.
If you’re trying to figure out which of two competing selectors wins, try my free CSS specificity checker.
Want me to talk about your product? You can sponsor this site.