CSS @layer Reference

CSS cascade layers — @layer declaration, block, import — with precedence rules.

Reference for the CSS @layer at-rule — declaring layer order, layer blocks, layered @import, and how cascade layers interact with specificity and !important. It runs free in your browser on Gera Tools, with nothing uploaded.

Last updated Source: Gera Tools

How do cascade layers change precedence?

Cascade layers add a step to the cascade that runs before specificity. A rule in a later-declared layer beats any rule in an earlier layer, regardless of selector specificity. Within a single layer, normal specificity and source order apply as usual.

Organising the cascade with @layer

CSS cascade layers let you split a stylesheet into explicitly ordered groups so that source order and specificity no longer decide everything. A rule in a later layer beats one in an earlier layer regardless of specificity — making resets, frameworks and overrides predictable. This reference covers the at-rule forms and the precedence rules.

How it works

Declare the layer order once with a statement-form @layer, then add rules with the block form. Order is set by first appearance, so an upfront declaration is the safest pattern:

@layer reset, base, components, utilities;   /* fixes precedence */

@layer reset { * { margin: 0; } }
@layer base { a { color: blue; } }
@layer utilities { .text-red { color: red; } }   /* wins over base */
@import url("framework.css") layer(base);
@import url("theme.css") layer();   /* anonymous layer */

For normal declarations a later layer wins; unlayered rules outrank all layers. For !important declarations the order inverts — the earliest layer wins — and important unlayered styles rank lowest.

The precedence table

This is the full precedence ranking for normal declarations, from lowest to highest:

  1. Rules in the first-declared layer (e.g. reset)
  2. Rules in the second-declared layer (e.g. base)
  3. Rules in the third-declared layer (e.g. components)
  4. Rules in the last-declared layer (e.g. utilities)
  5. Unlayered rules (highest normal precedence)

For !important declarations, this order completely inverts:

  1. !important unlayered (lowest among important)
  2. !important in the last layer
  3. !important in earlier layers
  4. !important in the first-declared layer (highest among important)

This inversion is deliberate. It allows a base reset layer to enforce critical important rules (such as box-sizing) even if a component layer later adds its own important declarations.

Real-world layering pattern

A practical four-layer setup for a project that adopts a third-party design framework:

/* Declare order upfront, before any @import */
@layer reset, framework, components, utilities;

/* Place the framework in its designated layer */
@import url("tailwind.css") layer(framework);

/* Your components beat the framework regardless of specificity */
@layer components {
  .card { padding: 1.5rem; }
}

/* Utilities beat everything else in normal declarations */
@layer utilities {
  .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; }
}

Any unlayered rule you write after this block beats even the utilities layer, which is a handy escape hatch for genuine one-off overrides without resorting to !important.

Tips and notes

  • Declare the order upfront so import position cannot reshuffle layers.
  • Unlayered styles always beat layered normal styles — keep ad-hoc overrides there.
  • Nest layers with @layer outer { @layer inner { ... } } or outer.inner.
  • Use revert-layer to fall back to lower layers for one property.