CSS Nesting
Native CSS nesting lets you write rules inside other rules, keeping a component's styles — its children, states and media queries — together in one block. It works in every current browser, with no preprocessor needed.
Basic nesting
A nested rule applies to matching descendants of the parent — .card h3 and .card p here.
The & selector
& stands for the parent selector. &:hover means .btn:hover, &.danger means .btn.danger, and .toolbar & flips the relationship: a .btn inside .toolbar.
Nesting media and container queries
Conditional rules can go straight inside a selector, keeping responsive changes next to the styles they modify. Combinator-led nested selectors like > * work without &.
What nesting compiles to
.nav {
display: flex;
a {
color: inherit;
&:hover {
text-decoration: underline;
}
}
}
/* is equivalent to: */
.nav { display: flex; }
.nav a { color: inherit; }
.nav a:hover { text-decoration: underline; }
Differences from Sass
- Native nesting can't concatenate strings:
&__titleto produce.card__titleis a Sass feature, not CSS. Write.card__titleout in full. - The nested selector behaves like
:is(), which affects specificity:#main, .content { p { … } }gives the nestedprule the specificity of#mainfor both.
Don't nest too deeply
/* ✗ hard to read, high specificity, tied to the HTML structure */ .page { .main { .article { .content { p { color: #333; } } } } } /* ✓ flat and clear */ .article-content p { color: #333; }
Nesting mirrors the HTML structure, and deep nesting creates long, specific, fragile selectors — the very problem it seems to solve. A good rule of thumb is to nest no more than two or three levels, mostly for states (&:hover), modifiers (&.active) and queries.