Kerning

HomeArticles → Development

Development

CSS nesting, six months of using it properly

It shipped, it works, and it makes stylesheets worse unless you set a rule about depth.

Native nesting removed the last common reason to reach for a preprocessor. It has also, in every codebase I have seen adopt it quickly, made the stylesheet harder to read within a month.

The failure mode is familiar to anyone who used Sass in 2015. Nesting is pleasant to write and unpleasant to read: a selector four levels deep no longer exists anywhere in the file as a searchable string, so finding what styles an element means mentally assembling it from four places.

The rule that fixed it for us is two levels, and the second level is only for states and direct modifiers — `&:hover`, `&[open]`, `& > li`. Anything that would be a third level becomes its own top-level selector with a real class name. The file gets longer and every selector in it can be found with a search.

It shipped, it works, and it makes stylesheets worse unless you set a rule about depth.

Where nesting genuinely earns its place is media queries and container queries inside the component block. Keeping the responsive behaviour next to the rule it modifies, rather than in a breakpoint section 200 lines down, is the actual win — and it does not add selector depth at all.

One practical trap: the `&` is required in more places than people expect when a nested selector starts with an element name. The specification allows bare element selectors now, but older implementations disagreed, so a bare `p { }` inside a block may silently do nothing in a browser from 2023. Write `& p` and it works everywhere.

TR
Tobias Ruiz

Senior writer · Austin

Front-end developer who got tired of watching good designs die in implementation. Covers browser features and the unglamorous work of making pages fast.

Read next

Get this in your inbox

One email on Thursdays with what we published and what else was worth reading.

One email on Thursdays. Unsubscribe in a click.