CSS Nesting Is Native Now - Here's What Sass Habits to Keep and Drop
The single most-cited reason to use Sass - nesting - has been native in every browser since 2023. No build step, no .scss extension, just write it:
.card {
padding: 1rem;
border: 1px solid #e2e8f0;
h3 {
margin: 0 0 8px;
font-size: 1.1rem;
}
&:hover {
border-color: #94a3b8;
}
&.featured {
border-width: 2px;
}
@media (min-width: 768px) {
padding: 1.5rem; /* media queries nest INSIDE rules now */
}
}
That nested media query deserves a highlight: the breakpoint variation lives with the component instead of in a distant section of the file. It's the organizational win people actually wanted from nesting.
The & rules worth internalizing
&:hover,&.featured,&[data-state="open"]- compound selectors (no space: "this same element with...") require the &.- Descendants don't:
h3 { }inside .card means .card h3. (Early implementations required &-prefixes for bare element selectors; the relaxed syntax shipped everywhere long since.) - & at the end flips the relationship:
.sidebar & { }inside .card means ".card when inside .sidebar" - the context-override pattern, no un-nesting required.
Where it is not Sass
The one to know: no string concatenation. The Sass idiom &__title for BEM does not work - & is a live selector reference, not text. Nested selectors are real selectors:
/* Sass habit that won't compile-because-there's-no-compiler: */
.card { &__title { } } /* ✗ does not create .card__title */
.card { .card__title { } } /* ✓ or just don't BEM inside nesting */
Honestly, native nesting reduces the need for BEM's flat naming in the first place - scoping is what the nesting does. Also unlike Sass: nested rules can't precede declarations mid-rule in odd ways (keep declarations first, rules after - which is good style anyway).
Keep the old discipline: nest shallow
Sass taught everyone the over-nesting lesson; it applies unchanged. Every level adds specificity and couples your CSS to DOM structure - three levels deep means a markup refactor breaks styling. My working limit: component root, its states (&), its direct meaningful children, one media query. If you're nesting four deep, you wanted a new class. (And when specificity from nesting bites, :where() zeroes it out.)
Support: Chrome 120+/Firefox 117+/Safari 17.2 for the relaxed syntax that matters - i.e., everything current. For many small-to-medium sites, this plus custom properties quietly removes the last reason the build pipeline existed.
Full-stack web developer sharing practical tutorials and building tools that ship.
Got something on your mind?
My inbox is open - no forms disappearing into the void here.
- Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
- Hire me for a project Have something custom in mind? Let's talk scope and timelines.
- Product support Bought something here? I'll help you get it running.
I usually reply within 1-2 business days.