Under The Hood
frontend css CSS Cascading and Inheritance Level 5 (@layer, all modern browsers)

Cascade Layers @layer: Specificity Overrides & Unlayered Styles

Last updated
Prerequisites:
CSS specificity and the cascade
Experience with CSS reset/component stylesheet organization
  • css
  • cascade
  • layers
  • specificity
  • at-layer
  • stylesheet-architecture

Read at your depth

The practical view

@layer lets you group styles into named layers whose priority is decided by declaration order, independent of specificity. @layer reset, base, components, utilities;. Rules in later layers win over earlier layers even with lower specificity. Unlayered styles (written outside any @layer) beat ALL layered styles — a common gotcha. Re-declaring layers in the same order later lets you reorder them: @layer utilities, components; moves utilities last so they win. Use layers to replace specificity wars between reset, third-party CSS, and your components.

The same idea in other frameworks

react equivalent
CSS modules per component + a global @layer setup gives predictable override order for component libraries.

Legacy vs modern

Specificity arms race vs cascade layers

Specificity wars need ever-more-specific selectors; @layer decides priority by declared order, so a simple class in a later layer wins cleanly.

before → after
Specificity escalation
body .widget .btn--primary { color: red; } /* ❌ OLD: higher specificity to beat the base rule */
Declared layer order
@layer base, components, overrides;
@layer overrides { .btn--primary { background: red; } } /* ✅ NEW: wins by layer order */

Interview gotchas

Context

This is the most common @layer surprise in production — interviewers test whether you understand that unlayered styles are an implicit final layer, which changes how overrides resolve.

The mechanical answer

The cascade assigns unlayered author styles the highest layer priority — as if they belonged to an implicit layer declared after all explicit layers. That means any style written outside @layer (which includes most legacy CSS) wins over layered rules of equal specificity regardless of the @layer order. During migration this is usually desirable (your existing overrides keep winning), but it silently defeats attempts to make a new utility layer beat legacy component styles until you move the legacy styles into a layer. The fix is to wrap legacy stylesheets (e.g. via @import url(...) layer(legacy)) so they participate in the layer order instead of sitting at the top.

Trap

The naive answer is 'unlayered styles lose to layered ones'. They win, because unlayered is the implicit last layer. Another trap: assuming @layer resets specificity entirely — within the same layer, specificity and source order still apply normally. Candidates who mention the implicit-final-layer behavior show they have actually shipped layers.

Under The Hood — a multi-depth technical interview hub.

Third-party licenses Press ⌘ K to search.