Cross-posted to webinista.com. Please link to that verison.
UPDATE April 9, 2023: CSS Nesting is now available in stable versions of Google Chrome and Microsoft Edge. Firefox support is still a question mark at this point. If you'd like to use CSS Nesting today, consider using the graceful degradation technique described at the end of this piece.
Pre-processors such as Sass and Less introduced nesting to CSS development. Nesting refers to the ability to group related CSS rules inside of a parent ruleset. It speeds the process of writing CSS because you don't have to re-type selectors. It can also improve the readability and maintainability of CSS by grouping related styles.
CSS Nesting syntax resembles that of Sass/SCSS and Less, but its grammar has some significant differences. I’ll cover some of those differences in this piece. I'm also assuming that you're familiar with Less or Sass/SCSS and CSS.
Nesting syntax basics
As with SCSS and Less, nested rulesets are contained within a parent declaration block. However, CSS Nesting requires that nested selectors begin with a relative selector or the nesting selector (
&). Otherwise, the nested rule is ignored.
In example 1, the nested
img ruleset is invalid CSS. This syntax is perfectly fine for pre-processors. Less and Sass both transform that selector to
.parent img. This syntax does not work for native nesting.
Relative selectors are a category of CSS selector. They include:
- id selectors such as
- class selectors, e.g.
- attribute selectors, such as
- pseudo-class selectors like
- pseudo-elements such as
- and selectors that begin with a combinator, such as
To match type elements in a nested rule you can either:
- Use a combinator.
- Prefix it with the nesting selector.
- Use the
Here's a rewritten version of the nested
img ruleset from example 1.
& img or
:is(img) makes the ruleset valid.
Invalid nested rules and their parent rules
Although browsers ignore invalid nested rules, an invalid nested rule does not invalidate its parent ruleset. In this case, elements that match
.parent will still have red text. Invalid rules can, however, prevent subsequent nested rules and declarations from being applied. Sibling rulesets or declaration added after the
img ruleset would bZ ignored.
Using the nesting selector multiple times
& nesting selector works a bit like a variable or placeholder for the selector of its parent rule. You can use the nesting selector anywhere in a selector list, and you can use it more than once. Example 2 demonstrates how to style nested unordered lists using the nesting selector.
Note the use of
& & with a space — the descendant combinator — between each ampersand. It's the equivalent of
CSS Nesting is not a drop-in replacement for pre-processors. Sass/SCSS, for example, uses the
& as a concatenation operator within nested rulesets (example 4).
When compiled, Sass converts SCSS to valid CSS (example 5).
CSS Nesting does not support this at all. You need to type the full
.accordion__trigger selector, whether or not you nest those rulesets.
You also can't use the nesting selector to represent pseudo-elements. The following CSS does not work.
Nesting requires that the resulting selector is a valid one. Note that pre-processors still compile this to CSS. In both cases, however, browsers will ignore the rule set. After all,
.subhead::before:hover is not a valid selector.
Nesting multiple levels
The CSS Nesting specification does not specify a maximum nesting level. In the example that follows, rules are nested four levels deep.
Unlike pre-processors, nested native CSS does not result in larger CSS files. You may, however, choose to limit nesting depth to maximize the reusability and readability of your CSS.
Nesting alone does not increase the specificity of a selector compared to its un-nested equivalent. In other words, the rulesets below have the same specificity.
The more you nest, however, the more specific your selectors become. Highly-specific selectors can make it difficult to reuse existing CSS to create new layouts and variations of components.
Order of appearance
Nested rules are always handled as though they occur after the parent rule, even if that's not how they're ordered in the source. Consider example 9.
It's the equivalent of the CSS shown in example 10.
For the sake of readability, group your parent rule's declarations together, at the top of the declaration block.
Yes, you can also nest at-rules within a ruleset. This includes conditional at-rules, such as
@supports. It also includes the
@layer rules. The syntax is nearly identical to the way it's done in SCSS and Less.
The preceeding CSS equivalent to the CSS in example 12.
When parsed, the at-rule is applied as though it follows its parent rule. Specificity, cascade, and inheritance behave as you'd expect.
Testing for CSS Nesting support
You can use
@supports and its
selector() function to conditionally apply CSS in browsers that support nesting.
Since the fallback for nested CSS is to use un-nested CSS, though, this does not make much sense. You'd end up sending about twice as much CSS over the network.
An alternative is to use the CSS Object Model and the
to conditionally load a style sheet that contains nesting if the browser supports CSS Nesting, to load a Sass- or Less-compiled style sheet if the browser does not support CSS Nesting. of the style sheet if it does not.
Bear in mind, however, this technique doesn't yet work with Safari. As of this writing, Safari Technology Preview returns
CSS.supports('selector( & )').
Can I use it?
CSS Nesting is
only available in the development / experimental versions of Chrome Edge, . and Safari Its specification is still in flux. Behavior and syntax could change between now and when CSS Nesting ships in stable browser versions. development of this feature has not yet begun. Firefox which still has about 6% of desktop marketshare in the United States.
That said, it is a great time to experiment with CSS Nesting. If Sass or Less is part of your workflow, prepare your
.scss files for a shift to native nesting. Eliminate instances where you've used
& as a concatenator. Move away from variables in favor of using CSS Custom Properties. Begin rewriting and removing mixins, extends, exports, and functions.
Avoid using CSS Nesting in public-facing, production sites for now, though. Your CSS will fail for most of your audience.