The CSS Nesting module allows you to write your stylesheets so that they are easier to read, more modular, and more maintainable. As you are not constantly repeating selectors, the file size can also be reduced.
CSS nesting is different from CSS preprocessors such as Sass in that it is parsed by the browser rather than being pre-compiled by a CSS preprocessor. Also, in CSS nesting, the specificity of the &
nesting selector is similar to the :is()
function; it is calculated using the highest specificity in the associated selector list.
This guide shows different ways to arrange nesting in CSS.
Note: Early versions of the specification did not allow nesting of type selectors without the &
nesting selector. This has been updated so the &
nesting selector is no longer needed. At the time of writing (Aug. 2023) Firefox supports the new version of the specification while Chrome and Safari support the old version of the specification and must use the &
nesting selector for type selector nesting.
Child selectors
You can use CSS nesting to create child selectors of a parent, which in turn can be used to target child elements of specific parents. This can be done with or without the &
nesting selector.
There are certain instances where using the &
nesting selector can be necessary or helpful:
- When joining selectors together, such as using compound selectors or pseudo-classes.
- For backwards compatability.
- As a visual indicator to aid with readability, when seeing the
&
nesting selector you know that CSS nesting is being used.
parent {
child {
}
}
parent {
& child {
}
}
parent {
}
parent child {
}
Examples
In these examples, one without and one with the &
nesting selector, the <input>
inside the <label>
is being styled differently to the <input>
that is a sibling of a <label>
. This demonstrates the impact of omitting the &
nesting selector.
Note: This example demonstrates different outputs in browsers implementing the original specification versus the current nesting spec. The original, pre-August 2023 nesting spec that was implemented in Chrome or Safari, requires the &
nesting combinator. If your browser supports the current spec, the output of both examples matches that of the second example.
Without nesting selector
HTML
<form>
<label for="name">Name:
<input type="text" id="name" />
</label>
<label for="email">email:</label>
<input type="text" id="email" />
</form>
CSS
input {
border: tomato 2px solid;
}
label {
font-family: system-ui;
font-size: 1.25rem;
input {
border: blue 2px dashed;
}
}
Result
With nesting selector
HTML
<form>
<label for="name">Name:
<input type="text" id="name" />
</label>
<label for="email">email:</label>
<input type="text" id="email" />
</form>
CSS
input {
border: tomato 2px solid;
}
label {
font-family: system-ui;
font-size: 1.25rem;
& input {
border: blue 2px dashed;
}
}
Result
Combinators
CSS Combinators can also be used with or without the &
nesting selector.
Example
Nesting the sibling combinator
In this example, the first paragraph after each <h2>
is targeted with the next-sibling combinator (+
) using CSS nesting.
HTML
<h2>Heading</h2>
<p>This is the first paragraph.</p>
<p>This is the second paragraph.</p>
CSS
h2 {
color: tomato;
+ p {
color: white;
background-color: black;
}
}
Result
Compound selectors
When using compound selectors in nested CSS you have to use the &
nesting selector. This is because the browser will automatically add whitespace between selectors that do not use the &
nesting selector.
In order to target an element with class="a b"
the &
nesting selector is needed otherwise the whitespace will break the compound selector.
.a {
.b {
}
&.b {
}
}
.a {
}
.a .b {
}
.a.b {
}
Example
Nesting and compound selectors
In this example the &
nesting selector is used to create compound selectors to style elements with multiple classes.
HTML
<div class="notices">
<div class="notice">
<h2 class="notice-heading">Notice</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</div>
<div class="notice warning">
<h2 class="warning-heading">Warning</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</div>
<div class="notice success">
<h2 class="success-heading">Success</h2>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit.</p>
</div>
</div>
CSS
Styles for the .notices
to create a column using flexbox layout
.
.notices {
display: flex;
flex-direction: column;
gap: 0.5rem;
width: 90%;
margin: auto;
}
In the CSS code below, nesting is used to create compound selectors both with and without &
. The top-level selector defines the basic styles for elements with class="notice"
. The &
nesting selector is then used to create compound selectors for elements with either class="notice warning"
or class="notice success"
. Additionally, the use of nesting to create compound selectors without explicitly using &
can be seen in the selector .notice .notice-heading:before
.
.notice {
width: 90%;
justify-content: center;
border-radius: 1rem;
border: black solid 2px;
background-color: #ffc107;
color: black;
padding: 1rem;
.notice-heading:before {
content: "ℹ︎ ";
}
&.warning {
background-color: #d81b60;
border-color: #d81b60;
color: white;
.warning-heading:before {
content: "! ";
}
}
&.success {
background-color: #004d40;
border-color: #004d40;
color: white;
.success-heading:before {
content: "✓ ";
}
}
}
Result
Appended nesting selector
The &
nesting selector can also be appended to a nested selector which has the effect of reversing the context.
This can be useful when we have styles for a child element that change when a parent element is given a different class:
<div>
<span class="foo">text</span>
</div>
As opposed to:
<div class="bar">
<span class="foo">text</span>
</div>
Example
Appending nesting selector
In this example there are 3 cards, one of which is featured. The cards are all exactly the same except the featured card will have an alternative color for the heading. By appending the &
nesting selector the style for the .featured .h2 can be nested in the style for the h2
.
HTML
<div class="wrapper">
<article class="card">
<h2>Card 1</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.</p>
</article>
<article class="card featured">
<h2>Card 2</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.</p>
</article>
<article class="card">
<h2>Card 3</h2>
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit.</p>
</article>
</div>
CSS
.wrapper {
display: flex;
flex-direction: row;
gap: 0.25rem;
font-family: system-ui;
}
In the following CSS we are creating the styles for .card
, .card h2
and then in the h2
styles we nest the .featured
class with the &
nesting selector appended which creates a style for .card .featured h2
.
.card {
padding: 0.5rem;
border: 1px solid black;
border-radius: 0.5rem;
& h2 {
color: slateblue;
.featured & {
color: tomato;
}
}
}
Result
Concatenation (is not possible)
In CSS preprocessors such as Sass, it is possible to use nesting to join strings to create new classes. This is common in CSS methodologies such as BEM.
.component {
&__child-element {
}
}
.component__child-element {
}
Warning: This is not possible in CSS nesting: when a combinator is not used, the nested selector is treated as a type selector. Allowing concatenation would break this.
In compound selectors, the type selector must come first. Writing &Element
(a type selector) makes the CSS selector, and the entire selector block, invalid. As the type selector must come first, the compound selector must be written as Element&
.
.my-class {
element& {
}
}
.my-class {
}
element.my-class {
}
Invalid nested style rules
If a nested CSS rule is invalid then all of the enclosed styles will be ignored. This does not affect the parent or preceding rules.
In the following example, there is an invalid selector (%
is not a valid character for selectors). The rule that includes this selector is ignored, but subsequent valid rules are not.
.parent {
& %invalid {
}
& .valid {
}
}