The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Nest a descendant | .card { .card__title { margin-block: 0; } } | View examples |
| Nest a direct child | .card { > img { inline-size: 100%; } } | View examples |
| Nest an adjacent sibling | .card { + .card { margin-block-start: 1rem; } } | View examples |
| Append a pseudo-class | .button { &:hover { background: #1d4ed8; } } | View examples |
| Require another class | .card { &.featured { border-color: #f59e0b; } } | View examples |
| Place context before parent | .card { .theme-dark & { background: #172033; } } | View examples |
| Nest a selector list | .field {
> input, > select, > textarea { inline-size: 100%; };
} | View examples |
| Account for parent specificity | .card, #featured-card { & .title { color: navy; } } | View examples |
| Keep parent weight low | :where(.card, #featured-card) {
& .title { color: navy; };
} | View examples |
| Put declarations first | .card {
color: #172033;
padding: 1rem;
& > h2 { margin: 0; };
} | View examples |
| Nest a media query | .card-grid {
@media (width >= 48rem) { grid-template-columns:
repeat(3, 1fr); };
} | View examples |
| Nest a feature query | .card {
@supports (text-wrap:
balance) { & > h2 { text-wrap: balance; } };
} | View examples |
| Nest a container query | .card {
@container (width > 30rem) { grid-template-columns:
8rem 1fr; };
} | View examples |
| Detect nesting support | @supports selector(&) {
.card { > .card__title { text-wrap: balance; } };
} | View examples |
| Provide a flat baseline | .card > .card__title { line-height: 1.2; } | View examples |
| Keep selector depth shallow | .dialog {
> header { } > .dialog__body { } > footer { };
} | View examples |
Native CSS nesting groups a component's declarations, related selectors, and conditional rules without a preprocessor. A nested selector is relative to its parent; & explicitly represents the parent match and is essential for states, compound selectors, and reversed context. Keep nesting shallow, put declarations before child rules, understand that & has :is()-like specificity, and preserve a non-nested baseline when older browsers are in scope.
Step by step
Detailed examples
Build descendant, child, and sibling relationships
A nested style rule accepts a relative selector list. A nested selector without a leading combinator is a descendant of the parent match; leading >, +, or ~ combinators express direct-child and sibling relationships. The browser behaves as though an implied nesting selector precedes each relative selector, so the explicit and implicit child forms have the same specificity.
.card {
.card__title { margin-block: 0; }
> img {
display: block;
inline-size: 100%;
}
+ .card { margin-block-start: 1rem; }
} .card .card__title { margin-block: 0; }
.card > img { display: block; inline-size: 100%; }
.card + .card { margin-block-start: 1rem; } Use & for parent states, compounds, and outer context
Inside a nested selector, & represents the elements matched by the parent rule. It removes the implicit descendant gap in &:hover and &.featured, and it can appear later in a selector such as .theme-dark &. Unlike string-based preprocessor substitution, native nesting cannot concatenate & into a new identifier: &--featured is invalid, so use an explicit class such as &.card--featured instead.
.card {
transition: border-color 160ms ease;
&:hover { border-color: #2563eb; }
&.featured { border-color: #f59e0b; }
.theme-dark & {
background: #172033;
color: #f8fafc;
}
} Predict selector-list expansion and specificity
Nested selector lists avoid repeating the parent, but & behaves like :is() for specificity: it takes the largest specificity among the complex selectors in the parent list. Therefore an ID in .card, #featured-card raises the parent portion of every nested match, even when .card matched. If that weight is undesirable, group the alternatives inside :where(), whose own specificity is always zero.
.field {
> input,
> select,
> textarea { inline-size: 100%; }
}
:where(.card, #featured-card) {
& .title { color: navy; }
} Note: Without :where(), a parent list containing #featured-card gives & ID-level specificity for every expanded nested selector.
Keep direct declarations before nested rules
Modern nesting syntax permits declarations before, between, or after nested rules. Interleaved declarations that occur after rules are represented as nested declarations rules so their cascade order stays where it was authored. That model is accurate but harder to scan, and older nesting implementations may skip trailing declarations. Put a rule's direct declarations first, followed by its nested style and group rules.
.card {
color: #172033;
background: #ffffff;
padding: 1rem;
& > h2 { margin-block-start: 0; }
&:focus-within { outline: 2px solid #2563eb; }
} .card {
color: #172033;
& > h2 { margin: 0; }
/* Valid in current nesting, but harder to reason about here: */
background: #ffffff;
} Note: The final declaration retains its authored cascade position; move it up for readability rather than assuming the browser hoists it.
Place media, support, and container conditions near a component
Conditional group rules can be nested inside a style rule. Declarations directly inside the condition apply to the parent selector, while nested style rules keep building from the same parent context. A container query still needs a suitable ancestor query container; placing @container inside .card does not make that card its own query container.
.card-grid {
display: grid;
gap: 1rem;
@media (width >= 48rem) {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
.card {
display: grid;
@supports (text-wrap: balance) {
& > h2 { text-wrap: balance; }
}
@container (width > 30rem) {
grid-template-columns: 8rem 1fr;
}
} Ship a flat baseline when older browsers remain in scope
Browsers that do not understand nesting ignore nested syntax, so essential layout should not depend on it unless the supported-browser policy guarantees native nesting. Author a flat baseline first, then place optional nested behavior inside @supports selector(&). The selector() test checks whether the parser supports the nesting selector; it does not test every other feature used inside the block.
.card > .card__title {
line-height: 1.2;
}
@supports selector(&) {
.card {
> .card__title { text-wrap: balance; }
&:focus-within { outline: 2px solid #2563eb; }
}
} Note: Keep the baseline outside the feature query; unsupported browsers discard the query block but retain the flat rule.
Nest around component relationships, not DOM indentation
Nesting is an organizational tool, not a requirement to reproduce the document tree. Deep nesting increases selector coupling, makes specificity less obvious, and causes markup changes to break distant rules. Prefer one or two meaningful relationship levels, use stable component classes, and start a new top-level rule when a child has its own reusable behavior.
.dialog {
border: 0;
border-radius: 0.75rem;
> header { border-block-end: 1px solid #cbd5e1; }
> .dialog__body { padding: 1rem; }
> footer { display: flex; justify-content: flex-end; gap: 0.5rem; }
}
.dialog__close {
min-inline-size: 2.75rem;
min-block-size: 2.75rem;
} Local code tester
Try native CSS nesting
Edit shallow nested selectors and conditional rules for a self-contained card component.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



