"Cascade layers end the !important wars. Native nesting eliminates the Sass build step. Both make CSS read like the architecture you intended."
The Cascade Layer Problem It Solves
Before layers, the cascade resolved conflicts by origin → specificity → source order. This made multi-stylesheet projects fragile: a third-party library's .btn { ... } could be overridden by your app's .btn { ... } only if your specificity matched or beat the library's, or if you used !important. Specificity wars proliferated; !important escalated; refactoring became dangerous.
Cascade layers introduce explicit ordering as a higher cascade priority than specificity. You declare layer order once; rules in later layers always beat earlier layers, regardless of specificity.
The @layer Syntax
Three ways to use it:
- Declare order:
@layer reset, library, app;— establishes the layer names and order (earliest to latest). Layers declared later beat layers declared earlier. - Put rules in a layer:
@layer app { .btn { ... } }. - Import into a layer:
@import url('library.css') layer(library);— pulls a whole stylesheet into a named layer.
The Canonical Stack
The pattern most modern stylesheets use:
How Cascade Layers Resolve Conflicts
The full cascade order, with layers added:
- Origin and importance.
- Cascade layer. Later-declared layers beat earlier layers. Rules outside any layer are between layered rules and inline styles — they beat layered rules.
- Specificity. Within the same layer.
- Source order. Final tiebreaker.
So .btn { background: red } in the library layer is beaten by .btn { background: green } in the app layer, regardless of specificity. No !important, no specificity escalation.
Anonymous Layers
@layer { ... } (no name) creates an anonymous layer. Useful when you don't need to reference the layer by name elsewhere. Anonymous layers are ordered in declaration order.
Native CSS Nesting
The & selector lets you nest rules inside other rules, exactly like Sass — but built into the browser. Baseline 2023:
The & Selector In Depth
&represents the parent selector..card { & .title { ... } }=.card .title { ... }.&:hover=.card:hover(no space).& > p=.card > p.&.featured=.card.featured(compound).- Use
&explicitly when needed; for direct descendants, the syntax allows skipping it:.card { .title { ... } }=.card .title { ... }.
Nesting + At-Rules
You can nest @media, @container, and @supports inside selectors. This is a huge readability win — the responsive variants of a component live next to the component's base rules:
Combining Layers + Nesting
Put nested rules inside a layer for maximum locality:
!important wars or a Sass build step that exists only for nesting, you're maintaining infrastructure the browser now provides for free.Pippa's Note
!important in the project except for explicit accessibility overrides. The cwk-site uses native nesting in component CSS files — each .component.module.css groups its base rule, hover state, focus state, and responsive variants in one place. The Sass dependency was removed from cwk-site in late 2025; native nesting covers all the use cases.