On this page
Native CSS nesting lets related selectors live together without requiring a preprocessor. It can reduce repeated component prefixes, but it can also disguise complex selectors and unexpectedly strong rules. The useful question is not how deeply you can nest, but which relationships become clearer when shown together.
Choose a small component to reorganize
Take a component with a base rule, a hover state, and one child element. Use the CSS to Tailwind converter to inspect the individual declarations if your team also maintains utility-based variants. Keep that comparison separate from the nesting change: this guide preserves ordinary CSS rather than moving the component to another styling system.
Aim for local readability. A reviewer should be able to understand the generated selector without mentally expanding several ancestors. One level for a state or child is often enough. Deeply nested CSS still creates deeply coupled selectors, even when the source looks neatly indented.
Before editing, save examples of the component in all supported states. Include a nested instance if your application permits components inside themselves. That fixture catches accidental descendant matching that a single isolated example will not reveal.
Learn what the nesting selector represents
The ampersand represents the parent selector in a nested rule. It is especially useful for pseudo-classes, compound selectors, and relationships that are not ordinary descendants. A nested rule without an ampersand can represent a descendant, but explicit syntax often communicates intent more clearly.
.download {
display: inline-flex;
gap: 0.5rem;
padding: 0.75rem 1rem;
&:hover {
text-decoration: underline;
}
&:focus-visible {
outline: 2px solid currentColor;
outline-offset: 3px;
}
& > .download__icon {
inline-size: 1.25em;
block-size: 1.25em;
}
&.is-busy {
cursor: progress;
}
}There is a meaningful difference between &.is-busy and & .is-busy: the first matches the same element with both classes; the second matches a descendant. That space changes the selector, not merely its formatting.
Use MDN’s nesting guide as a reference. Native nesting is parsed by the browser; it is not Sass syntax copied into a stylesheet and interpreted with identical rules.
Avoid Sass-specific concatenation assumptions
A common preprocessor pattern appends a suffix to a parent selector, such as an element or modifier name. Native nesting does not provide Sass-style string concatenation through the ampersand. Write the complete class name explicitly when that is the component’s naming convention.
For example, keep .download__label as a separate rule or select it as & > .download__label when the structural relationship is intentional. Do not turn a naming convention into a dependency on a particular ancestor unless the component actually requires that relationship.
This is a selector boundary decision. Separate classes remain reusable across markup arrangements, while descendant rules express coupling to a parent. Neither is universally better, but a mechanical conversion can silently change the architecture if it adds ancestors everywhere.
When migrating from Sass, first identify variables, mixins, functions, imports, and selector interpolation. Native nesting replaces only the nesting feature. It does not automatically replace every build-time capability used by your existing stylesheet pipeline.
Keep specificity and selector lists visible
Nesting interacts with specificity similarly to the :is() pseudo-class. When the parent is a selector list, the most specific selector in that list can influence the nested rule. Combining an ID selector with a class selector can therefore give a nested rule more weight than its class-only appearance suggests.
Avoid mixed-specificity lists when possible. A shared visual declaration can be duplicated briefly or extracted into a low-specificity class rather than coupling unrelated selectors under one powerful parent list. Fewer source lines are not worth less predictable overrides.
MDN’s nesting specificity explanation provides worked examples. Check the compiled or browser-interpreted selector when a utility suddenly stops winning after a refactor that supposedly changed only formatting.
Set a depth limit that matches your team’s review habits. Two nested levels is a reasonable starting convention, not a CSS rule. If a third level describes a meaningful independent component, move that component’s styles out instead of preserving the entire page hierarchy in the selector.
Handle conditional rules and migration carefully
You can place a media query inside a component rule so the responsive variation stays near the base declarations. This is useful for one component-specific adjustment; it becomes less useful when every property has its own nested condition spread throughout the file.
Keep responsive intent explicit. Group related changes under one condition and explain why the threshold exists. Avoid creating a maze of nested selectors inside nested queries inside another component’s rule. The browser may understand it perfectly while maintenance becomes unnecessarily difficult.
The CSS Nesting specification is the formal reference. For older browser targets, determine whether your build tool transforms native nesting and which syntax version it supports. A source file accepted by an editor is not proof that every deployment target can parse the emitted CSS.
Be cautious with declarations placed after nested rules when supporting older implementations or transforms. Group base declarations first for a simple, conservative authoring style. If preserving mixed declaration order matters, test the actual served result rather than assuming every tool version handles it identically.
Review the change alongside the existing design token guidance, but keep it narrowly scoped. Renaming variables, changing spacing, replacing classes, and introducing nesting in one patch makes regressions much harder to attribute.
Include nested instances and external overrides in your regression fixtures. A rule that was previously .download__icon but becomes .download .download__icon can now affect icons inside a nested download component. Use direct-child combinators or independent class rules when that distinction matters.
Finish by documenting the chosen conventions in your development reference: maximum depth, explicit ampersands, selector-list policy, and whether source CSS is transformed. Those decisions make native nesting a readability feature rather than a new source of hidden selector behavior.
Key takeaways
- Use nesting to group meaningful relationships, not to mirror the entire DOM.
- Distinguish compound selectors from descendants by inspecting whitespace.
- Replace Sass concatenation explicitly rather than assuming identical syntax.
- Watch specificity when parent selector lists contain stronger selectors.
- Verify the emitted CSS and keep migration patches focused.
Reach designers & developers at work
Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.
Become a sponsor