The @layer at-rule is the closest thing CSS has to a built-in version of ITCSS's ordering philosophy — except it's enforced by the browser itself, independent of selector specificity or file order.
1Declaring Layer Order Up Front
A bare @layer reset, base, components, utilities; statement, with no rules inside it, does one job: it establishes the relative priority of those four layer names, in that order, before any of them are actually populated with CSS. You can then define each layer's rules anywhere else in the file, or across separate imported files, and the priority order established upfront still applies.
This separation is deliberate and powerful: the *architecture decision* (what order should things cascade in) is made once, in one visible place, completely decoupled from the *implementation* (which files define which rules).
2Why This Is A Genuine Paradigm Shift
Every CSS developer learns early that ID selectors are nearly impossible to override without an equally strong selector or !important. Cascade Layers change this fundamentally: layer order is evaluated *before* specificity is ever considered. A single-tag selector in a later layer beats an ID selector in an earlier layer, every time.
This makes @layer a genuinely better tool than ITCSS's file-ordering trick for the same goal — ITCSS relies on developer discipline to keep specificity increasing through the file; @layer makes that guarantee structural and browser-enforced, immune to accidental specificity creep in any individual rule.
3The Unlayered CSS Gotcha
Any rule written outside of an @layer block is implicitly treated as its own final layer, positioned *after* every named layer — meaning unlayered CSS always wins, regardless of the order you declared your named layers in. This is the single most common surprise when adopting @layer incrementally in an existing project: your carefully ordered layers can be silently overridden by old, un-migrated CSS still sitting outside any layer.
The practical mitigation is deliberate: either migrate all existing CSS into an explicit layer (even a low-priority @layer legacy at the very start) during rollout, or treat any remaining unlayered CSS as an intentional 'always wins' escape hatch, similar to how ITCSS reserves Trumps for the same purpose.
4Step-by-Step Breakdown
Cascade Priority, Decoupled From Specificity. For decades, controlling which CSS rule wins meant fighting with specificity and source order simultaneously — the two were inseparable. The native @layer at-rule changes that: you can now declare explicit priority order between named layers, completely independent of how specific each layer's selectors are.
Declaring And Ordering Layers. A single @layer statement listing names establishes their priority order once, up front, regardless of where each layer's actual rules are defined later in the file or across separate files. Layers listed first have the lowest priority; layers listed last win, even against a layer with higher specificity selectors.
Layer Priority Order. In @layer reset, base, components, utilities;, which layer has the highest cascade priority?
- →reset
- →base
- →utilities
Specificity Is Neutralized Within The Layer System. This is the feature's core superpower: an ID selector inside an earlier layer still loses to a plain tag selector inside a later layer. Layer order is checked before specificity at all — specificity only matters for breaking ties between rules within the same layer.
Layers Override Specificity. Given the code example, which color does the h1 actually render as?
- →Red — the ID selector in 'base' wins on specificity
- →Blue — the 'override' layer has higher priority than 'base', regardless of specificity
- →Neither — this is invalid CSS
Unlayered Styles Always Win Last. Any CSS rule not wrapped in an @layer block is treated as belonging to an implicit final layer with the absolute highest priority — higher than every named layer, no matter the order they were declared in. This means third-party or legacy unlayered CSS will always take precedence over your layered styles unless you explicitly wrap it too.
The Unlayered Gotcha. A rule outside any @layer block competes against a rule inside a declared layer. Which one wins?
- →The layered rule, since layers were explicitly declared
- →The unlayered rule — it implicitly belongs to the highest-priority layer of all
- →Whichever has higher specificity, as usual
Native Layer Control Unlocked. You now understand how native CSS Cascade Layers decouple priority from specificity entirely, why later-declared layers always win regardless of selector strength, and the critical gotcha that unlayered CSS always wins over every layer. This gives ITCSS-style layering a native, browser-enforced mechanism instead of relying purely on file import order.
Win The Cascade With Layer Order. Later @layer declarations win over earlier ones, regardless of selector specificity, as long as both rules are layered.
Level Up 🚀
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1A Dedicated Overrides Layer Is A Safer Home For Accessibility Patches Than !important
Instead of reaching for !important to force an urgent accessibility fix (like a missing focus outline) to take effect, placing it in a deliberately final layer achieves the same guaranteed priority without permanently escalating that specific declaration above the normal cascade forever.
2Third-Party Unlayered CSS Can Silently Override Layered Accessibility Styles
Because unlayered CSS always wins over every named layer, an unlayered third-party stylesheet (like a widget or ad script) can override your carefully layered focus or contrast styles without any specificity conflict warning you it happened.
SEO Implications
- 1
Cascade Layers Reduce Reliance On !important, Improving Long-Term CSS Maintainability
Since layer order alone can guarantee priority, teams need !important far less often, which keeps future CSS changes easier to reason about and reduces the maintenance overhead that indirectly slows down large-scale redesigns.
- 2
Explicit Layer Structure Makes Automated Critical-CSS Tooling More Reliable
Because @layer gives tooling an explicit, declared priority structure to read, extracting a correctly-ordered critical CSS subset for above-the-fold rendering becomes less error-prone than inferring intent from file order alone.
Best Practices
Declare All Layer Names In One Place, Near The Top Of Your Entry Stylesheet
A single, visible @layer statement listing every layer name in priority order acts as living documentation of your cascade architecture, readable without hunting through every imported file.
Explicitly Wrap Any Third-Party CSS You Don't Control Into Its Own Layer
This prevents unlayered third-party styles from automatically outranking your entire layered architecture, and lets you deliberately position that vendor CSS wherever it should actually sit in priority.
Frequent Bugs
After incrementally migrating a codebase to @layer, some old, un-migrated styles keep winning unexpectedly.
Unlayered CSS always has the highest implicit priority. Wrap the remaining legacy CSS in its own explicitly low-priority layer during migration.
A component styled inside a later-declared layer isn't overriding an earlier layer's ID selector as expected.
Confirm both rules are genuinely inside named @layer blocks — if one rule is accidentally unlayered, it wins regardless of the intended layer order.
Real-World Examples
Migrating An ITCSS Codebase To Native Layers
A team replaced their file-import-order-dependent ITCSS structure with explicit @layer declarations mirroring the same seven-layer names, making the priority guarantee browser-enforced instead of convention-dependent.
@layer settings, generic, elements, objects, components, trumps;