CSS Cascade Layers: Ordering Rules Before Specificity
CSS cascade layers organize rule precedence so teams can reduce specificity battles. This guide covers normal declaration order, the reversal for !important, and how unlayered rules interact with layered styles.
Publication & corrections: infostoa · Editorial standards
Individual author and specialist reviewer information is not provided for this article.
When a CSS rule loses, increasing selector specificity can create a harder conflict later. Cascade layers let authors group declarations into named layers and establish an explicit order among those groups. For declarations from the same origin and importance level, layer precedence is evaluated before selector specificity. That makes it possible to express relationships such as reset, base styles, components, and utilities in the stylesheet itself.
1. Layer order is evaluated before specificity
The cascade is not simply “the most specific selector wins.” It compares several criteria in a defined order, including origin and importance, cascade layer, specificity, and source order. When declarations compete within the same relevant origin and importance level, their layer order is considered before selector specificity. A highly specific normal rule in a lower-priority layer therefore does not automatically defeat a normal declaration in a later layer.
The order in which layers are first established matters. A statement such as @layer reset, base, components, utilities; makes the intended order visible before the rules are distributed across files. Rules can then be placed in blocks such as @layer components { ... }. Reusing a layer name adds declarations to that layer; it does not move the layer to a new position each time it appears. This is useful when a codebase imports styles from several teams or packages, but it also means the first declaration should be deliberate.
2. Normal declarations and unlayered CSS
For normal author declarations, a later layer takes precedence over an earlier layer. A normal author declaration outside every layer has higher precedence than normal declarations inside layers. As a result, legacy unlayered rules can override the layered groups during a gradual migration. Wrapping an old stylesheet in a layer can also change its behavior even when none of its selectors changed.
Start with a small component or page and inspect the winning declaration and computed value in browser developer tools. Check which files are imported, whether the declarations are actually inside a layer, and whether an unlayered rule remains. Layers provide one ordering mechanism; they do not remove the cascade’s other criteria, such as origin, inheritance, inline styles, or importance.
3. Important declarations reverse the layer order
Declarations marked !important do not follow the normal layer ordering. Among important declarations, the layer order is reversed: a declaration in an earlier layer takes precedence over an important declaration in a later layer. Important declarations outside layers also occupy a different position from normal unlayered declarations. The shortcut “the last layer wins” is therefore true only for normal declarations under the applicable cascade conditions.
This reversal is part of the broader handling of important declarations across origins, including user and user-agent styles. Adding layers does not make !important easier to reason about automatically. When an important declaration is necessary, record its origin and layer and first check whether clearer normal rules can express the intended design. A layer is not a replacement for forced overrides.
4. Practitioner perspective: a controlled migration and debugging method
First group rules by their real responsibility, such as reset, base, components, and utilities. Declare their order in one place, then verify how imported stylesheets join those layers. Test a representative route and inspect computed styles and overridden declarations. When the result differs from expectations, trace origin, importance, layer order, specificity, and source order in that sequence instead of repeatedly adding selector weight.
Layers can make boundaries between team or package styles explicit, but a layer name does not guarantee isolation or quality. Unlayered CSS, !important, and stylesheet loading order can still affect the result. Adopt layers on a limited surface, compare the actual cascade with the previous behavior, and expand only after the interactions are understood.