Skip to content
C Codeloom
HTML & CSS

CSS Nesting: Native Browser Support

Native CSS nesting is here. Learn the syntax, the ampersand rules, how it compares to Sass, common gotchas with pseudo-classes and media queries, and how to adopt it without breaking older browsers.

·4 min read · By Codeloom
Beginner 7 min read

What you'll learn

  • How native CSS nesting works without a preprocessor
  • When the ampersand is required and when it is implicit
  • How nested media queries and pseudo-classes behave
  • Differences from Sass and Less
  • How to adopt nesting safely in real projects

Prerequisites

  • Basic CSS knowledge

What and Why

CSS nesting lets you write child rules inside parent rules, the same way Sass and Less have for years. The difference is that browsers now do it natively. No build step, no preprocessor, no extra source map. You ship the file you wrote.

The why is locality. Component styles tend to live together: a button, its hover state, its disabled state, its variants. Writing them as separate selectors works, but you repeat the parent selector every time and your eye has to jump around. Nesting keeps related rules in one block, which makes refactors safer and intent clearer.

Mental Model

Think of a nested rule as syntactic sugar for a flattened selector that joins the outer and inner. By default, the inner selector is interpreted as a descendant. When you need the inner selector to attach to the parent itself, or to a sibling, use the ampersand & to refer to the parent.

Three rules cover ninety percent of cases:

  • Plain selector inside a rule means descendant.
  • & is replaced by the full parent selector.
  • Pseudo-classes and pseudo-elements always need & because they have no descendant interpretation.

Hands-on Example

.button {
  background: navy;
  color: white;
  padding: 0.5rem 1rem;

  /* descendant: a .icon inside .button */
  .icon {
    margin-right: 0.5rem;
  }

  /* attached to the parent itself */
  &:hover {
    background: darkblue;
  }

  /* variant class on the same element */
  &.primary {
    background: crimson;
  }

  /* media query nested inside */
  @media (min-width: 640px) {
    padding: 0.75rem 1.5rem;
  }
}
.button { ... }                .button { ... }
.icon { ... }       =>       .button .icon { ... }
&:hover { ... }              .button:hover { ... }
&.primary { ... }            .button.primary { ... }
@media (...) { ... }         @media (...) { .button { ... } }
How nested rules flatten to plain CSS

The flattened form is exactly what the browser computes. If you ever wonder what a nested block actually selects, mentally substitute the parent for & and concatenate.

Common Pitfalls

The biggest trap is forgetting & before a pseudo-class. .card { :hover { ... } } does not style the card on hover. It styles any hovered descendant of the card. You almost always meant &:hover.

Another trap is type selectors as the first token of a nested rule. Some early implementations required wrapping div { ... } in & div because a nested rule starting with a letter could be ambiguous. Modern engines accept the bare form, but if you support older releases, prefix with & to stay safe.

Nesting can also hide specificity creep. A four-level nest reads like a tree, but produces a long descendant selector that is hard to override later. Two levels is comfortable; four is a code smell.

Finally, nesting is not free for tooling. Make sure your linter, formatter, and CSS-in-JS bridge understand the syntax before you commit a wholesale refactor.

Best Practices

Use nesting for variants and states that genuinely belong to a component: hover, focus, disabled, modifier classes, media queries. Avoid nesting unrelated layout rules just because they happen to live in the same file.

Cap your nesting depth. A rough rule: if you cannot read the flattened selector in your head, you have nested too far. Extract a class instead.

Prefer & explicitly for pseudo-classes and combinators. The extra character makes the intent unambiguous and matches how preprocessors trained your muscle memory.

Check @supports selector(&) if you must support older browsers, and ship a flat fallback file via a build step. For evergreen targets, no fallback is needed.

Wrap-up

Native CSS nesting brings a preprocessor superpower into the browser. The mental model is small: descendant by default, & for self and combinators. Keep depth modest, prefer explicit &, and your stylesheets will be both shorter and easier to refactor.