Native CSS nesting

CSS · Advanced · 8 min

Nesting keeps component styles together and removes the main reason many projects used Sass.

CSS supports nesting natively in every current browser. Inside a rule you can write further rules that apply relative to the parent selector.

.card {
  padding: 1rem;
  & h2 { margin: 0; }          /* .card h2 */
  &:hover { background: #f8f8f8; }  /* .card:hover */
  .dark & { background: #222; }    /* .dark .card */
}

& stands for the parent selector. A nested selector without & is treated as a descendant, so h2 { } inside .card means .card h2 (the & is optional there). Use & explicitly when attaching pseudo-classes (&:hover) or when the parent goes in the middle or end (.dark &).

Media queries, container queries, @supports and @layer can nest inside a rule, applying to the current selector, which keeps responsive tweaks next to the styles they modify.

Differences from Sass to know:

  • No string concatenation: &__title (BEM-style suffixes) does not work.
  • & behaves like :is(parent), so specificity follows :is() rules: a parent list such as #a, .b is treated as if it were the id everywhere.
  • Declarations written after nested rules are allowed; they're treated as if in their original order.

Don't nest deeply. Each level adds specificity and couples styles to markup structure; one or two levels is plenty.

Example

.card {
  padding: 1rem;
  border-radius: 12px;

  & h2 { margin-block: 0 0.5rem; }        /* .card h2 */
  & > img { width: 100%; }                 /* .card > img */
  &:hover { box-shadow: 0 4px 16px rgb(0 0 0 / 10%); }
  &.featured { border: 2px solid gold; }   /* .card.featured */
  [data-theme="dark"] & { background: #1f2937; }  /* ancestor context */

  @media (width >= 48rem) {
    padding: 2rem;                         /* .card at wide widths */
  }
}

Remember

  • & is the parent selector; nested selectors default to descendants
  • Media and container queries can nest inside rules
  • No Sass-style &__suffix concatenation
  • Keep nesting to one or two levels

Watch out for

  • Porting Sass that relies on &-suffix concatenation and getting silently broken selectors.

Check yourself

  1. Inside .btn { ... }, what does '&.primary' select?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: developer.mozilla.org/en-US/docs/Web/CSS/Guides/Nesting/Using