What native nesting changes
Native nesting lets a selector live inside its parent, exactly like the preprocessors taught us — but with one crucial difference: it is the browser's own cascade, no build step, no indentation rules from a tool that left the room. The payoff is files that group a component's styles where the eye expects them: the card's padding, its title rule, and its hover state in one readable block instead of three scattered locations.
.card {
padding: 1.5rem;
border-radius: 1rem;
& h2 { font-size: 1.25rem; } /* descendant */
& > .title { font-weight: 700; } /* child */
&:hover { translate: 0 -2px; } /* self pseudo */
&.is-selected { border-color: var(--accent); }
@media (width < 640px) { padding: 1rem; } /* nested at-rule */
}The trap: specificity climbs silently
Every nesting level adds specificity. .card & h2 computes as (0,1,1) — one class, one type — while .card { & .title & .meta } keeps stacking. Deeply nested selectors quietly outrank the flat overrides you write later, and the 'why is my override not applying' hunt begins. The discipline: nest for grouping, not for depth. Two levels deep is the comfort zone; three is where you start paying.
& h2 and & .title and &:hover all behave differently from each other and from preprocessor habits. & concatenates the parent selector as-is: .card & h2 means 'h2 inside .card', but & .title inside .card means '.card .title' — the space matters. Read every & as 'the parent selector, literally here' and the syntax stops surprising you.
Mixing nesting with the cascade layers
Nesting composes beautifully with @layer: put the component layer inside the nesting and the whole file reads top-to-bottom as one story. Nesting is not a rewrite — it is a reorganization of files you already have, and the safest migration is bottom-up: nest one component a week, keep the specificity shallow, and let the cascade layers do the arbitration that nesting must not.