CSS & Frontend

CSS Nesting Is Here and Yes It Works Like You Think It Does

All articles
🪆

One Less Reason to Need a Preprocessor

The number one reason people reached for Sass was nesting. Being able to write .card and then nest .card__title, .card__image, and .card__body inside it was so much more readable than repeating .card at the start of every selector. It was the feature that made preprocessors feel essential. Native CSS nesting shipped in all major browsers in late 2023, and the relaxed syntax that removed the last major limitation landed in early 2024. You can now nest selectors in plain CSS files. No build step. No Sass. No PostCSS plugin. Just CSS. The basic syntax will feel immediately familiar if you've used Sass. You write your parent selector, open a block, and nest child selectors inside. .card { color: gray; .title { font-weight: bold; } } compiles to .card { color: gray; } .card .title { font-weight: bold; }. It works exactly how you'd expect. The ampersand (&) works like it does in Sass — it represents the parent selector. &:hover, &.is-active, &::before all work as expected. You can use it to compose compound selectors: .card { &.featured { border-color: gold; } } targets .card.featured. Here's where it gets interesting. The relaxed nesting spec removed the original restriction that nested selectors had to start with a symbol. In the initial spec, you couldn't write .card { p { ... } } because p starts with a letter. You had to write & p or :is(p). That limitation is gone. Element selectors nest directly now. This was the last thing preventing CSS nesting from being a true Sass replacement for this feature. Media queries nest inside selectors too. This is arguably more useful than selector nesting. Instead of writing your component styles at the top level and then repeating the selector inside a @media block at the bottom of the file, you can nest the media query right where the styles are. .sidebar { width: 100%; @media (min-width: 768px) { width: 300px; } }. Component styles and their responsive variations live together. This is a massive improvement for code organization. Nesting also works with @container queries, @layer, and @supports. You can nest feature queries right inside the component that uses them. This colocation of styles with their conditions makes CSS files dramatically easier to read and maintain. There are specificity differences from Sass that matter. In native CSS, the browser evaluates nested selectors differently than Sass does. .card { .title { ... } } is equivalent to :is(.card) .title in terms of how the browser processes it. In most cases this doesn't change the specificity outcome, but if you're nesting with complex selectors or :is()/:where(), the specificity calculation can surprise you. Test your specificity assumptions if you're migrating from Sass. How deep should you nest? The same advice from the Sass era applies: keep nesting shallow. Two or three levels maximum. Deep nesting creates overly specific selectors that are hard to override and hard to read. If you're nesting more than three levels, that's usually a signal that your component structure needs simplifying, not more nesting. For agencies, this changes the tooling conversation. We've dropped Sass from three client projects this year, replacing it with native CSS plus a few custom properties. The Sass features we still occasionally miss — mixins, extends, and math functions — are either available natively (calc(), custom properties, container queries handle most mixin use cases) or not worth the build step overhead. If your Sass usage is primarily nesting plus variables, you can switch to native CSS today with zero feature loss. The migration path is clean. Take your .scss files, rename them to .css, and most of the nesting works as-is. Fix any element selectors that need the relaxed syntax support (which is already shipped everywhere). Replace Sass variables with custom properties. Remove the Sass build step. Done. We've done this migration on production sites in under two hours. Is there still a case for Sass? Yes, if you're using its programmatic features heavily — loops, maps, complex functions, mixins that generate lots of utility classes. But for the 80% of projects where Sass was just nesting plus variables? Native CSS has you covered. CSS keeps absorbing the best ideas from the preprocessor ecosystem. Nesting was the big one. It's here, it's stable, and it works like you think it does.
Let us make some quick suggestions?
Please provide your full name.
Please provide your phone number.
Please provide a valid phone number.
Please provide your email address.
Please provide a valid email address.
Please provide your brand name or website.
Please provide your brand name or website.