Skip to main content

⬡ Zone 8

Cascade Layers

Tame the cascade. Control specificity.

Explore
← Observatory
Browser support: Chrome 99+ · Firefox 97+ · Safari 15.4+

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; }
}

Layer Ordering Sandbox

Drag layers to reorder them. The rightmost layer wins. Watch the demo element update live.

Drag to reorder — left = lowest priority, right = highest

@layer reset Normalizes browser defaults
@layer base Design system foundations
@layer components Reusable UI components
@layer utilities Atomic utility overrides
Current winner @layer utilities

Live preview

The cascade resolves here.

Color, font size, and border — each defined in every layer. The winning layer's values apply.

Generated CSS