What @layer does
The CSS cascade has long resolved conflicts in two stages: origin
(user agent < user < author < animations) and then within the
author origin by importance (!important flips order),
specificity, and source order.
Cascade Layers add a third stage within the author origin: a named, ordered set of layers between origin and importance. Author rules in a later-declared layer beat author rules in an earlier layer, regardless of selector specificity.
@layer reset, base, components, utilities;
@layer reset {
* { margin: 0; padding: 0; }
}
@layer base {
body { font-family: var(--font-body); line-height: 1.6; }
}
@layer components {
.btn { padding: 0.5rem 1rem; border-radius: 4px; }
}
@layer utilities {
.pad-0 { padding: 0; }
}
Even though .btn and .pad-0 have equal specificity, the
utilities layer wins because it was declared after
components. Source order within a layer still matters in the
usual way.
Why layers matter
Before @layer, authors used specificity wars: stack classes,
qualify with :where(), or escalate to !important. Each
escalation made future overrides harder. Layers let the cascade
do its job by intent rather than accident.
A practical sequencing pattern from Miriam Suzanne’s 2022 talk:
@layer reset, base, theme, layout, components, overrides;
- reset — UA normalisation.
- base — element defaults (typography, spacing scale).
- theme — design tokens, palettes.
- layout — page-level grid, containers.
- components — buttons, cards, forms.
- overrides — utilities, page-specific tweaks.
A rule in overrides always wins over a rule in components,
without bumping specificity. Multiple components can ship rules
in components without fighting one another.
Importing into layers
@import accepts a layer() function:
@import url("normalize.css") layer(reset);
@import url("framework.css") layer(components);
This puts a third-party stylesheet into a controlled layer. The
common gotcha is that some libraries declare their own
@layer ... { ... } blocks; the layer() import wraps the
entire file, which may produce nested layers like
reset.bootstrap.utilities.
Anonymous layers
@layer { ... } (no name) creates an anonymous layer that is
unique to its source position. Two anonymous layers in the same
file are separate; their relative order follows source order.
Anonymous layers cannot be re-opened by name later.
Reverting and unlayered rules
Rules outside any @layer block are unlayered and beat all
layered rules at the same origin. This is intentional: it lets
you escape the layer system with a quick rule:
@layer base, components, utilities;
@layer base { h1 { font-size: 2rem; } }
@layer components { .heading { font-size: 1.5rem; } }
h1.heading { font-size: 1.75rem; } /* unlayered — wins */
Avoid relying on this in mature codebases — the unlayered rule is invisible in the layer report tools.
DevTools support
Each engine’s DevTools surfaces layers in the Styles pane:
- Chromium DevTools (since 113, 2023) shows layer names next to matching rules.
- Firefox DevTools (since 117, 2023) shows layers in the inspector cascade view.
- Safari Web Inspector (since 16.4, 2023) shows layers in the Styles sidebar.
Pass-rate on the Cascade L5 layer test suite is about 98% across all three engines as of 2024.
Common pitfalls
- Forgetting to declare order at the top. Layer order is
fixed at first encounter; subsequent declarations cannot
reorder. Always declare
@layer a, b, c;first. - Mixing layered and unlayered rules. Unlayered rules beat layered ones — surprising when audit tooling assumes everything is in a layer.
!importantand layers. Importance ordering is reversed for layered rules: an!importantrule in an earlier layer wins over an!importantrule in a later layer. Combined with origin importance, this lets user-agent!importantstill win — but author authors are surprised.- Specificity inside a layer still matters. Layers do not
collapse specificity; they are an outer key. A high-specificity
rule in
componentsstill beats a low-specificity rule incomponents.
Cross-engine support
@layer reached interop in 2022 across Chromium 99 (March 2022),
Firefox 97 (February 2022), and Safari 15.4 (March 2022).
caniuse data reports
about 95% global support.
Further reading
- CSS Cascade Level 5, §5 Layered cascade.
- Miriam Suzanne’s Cascade Layers explainer (2022) — the canonical author-facing reference, by the spec editor.
- Una Kravets’s layered design system case study (2022) walks through migrating an existing codebase.
- Bramus’s collection of layer pitfalls
documents
@import layer()edge cases.