The cascade, tamed.
Before @layer, specificity wars plagued every stylesheet. A third-party component's .btn.primary would fight your .my-app .btn. You'd reach for !important and dig the hole deeper.
Cascade layers let you declare entire groups of styles as a named layer — and then set the priority of those layers explicitly. Specificity still matters within a layer, but layers always defeat lower-priority layers, regardless of selector weight.
Declaring layer order
The first place a layer name appears in the stylesheet establishes its priority. A common pattern: declare all layer names upfront in one statement.
/* Declare order first — lowest to highest priority */
@layer reset, base, components, utilities;
/* Now fill each layer — order of filling doesn't matter */
@layer utilities {
.mt-4 { margin-top: 1rem; }
}
@layer reset {
* { box-sizing: border-box; }
}
!important reverses layer priority
This surprises everyone at first: !important declarations in a lower-priority layer win over !important in a higher-priority layer. It follows the same rule as the normal cascade — important declarations are sorted in reverse.
@layer reset, base, utilities;
@layer utilities {
.text-red { color: red; } /* wins normally */
.text-red { color: red !important; } /* loses to reset's !important */
}
@layer reset {
.text-red { color: blue !important; } /* wins — reset has !important priority */
}
Unlayered styles always win
Any styles outside a layer are treated as an implicit highest-priority layer. This means your existing CSS won't be clobbered when you adopt @layer — a deliberate design choice for incremental adoption.
@layer base, utilities;
@layer utilities {
.btn { color: purple; } /* layer — loses */
}
/* Unlayered — always beats any @layer */
.btn { color: hotpink; } /* wins */
Nesting layers
Layers can be nested using dot notation or by nesting @layer blocks. This is powerful for organizing third-party library styles without polluting your own layer namespace.
/* Dot notation */
@layer framework.reset, framework.theme, framework.components;
/* Block nesting */
@layer framework {
@layer reset {
* { margin: 0; }
}
@layer components {
.card { padding: 1rem; }
}
}
/* Append to nested layer from outside */
@layer framework.components {
.card { border-radius: 0.5rem; }
}