Reference guide · html-css-js · Published 2026-08-16 · 3 min read

Native CSS nesting explained

Learn native CSS nesting, the ampersand rules and specificity behavior, and how it compares to preprocessor nesting in Sass.

Native CSS nesting lets you nest one rule inside another directly in a stylesheet, without a preprocessor. After years of being a Sass exclusive feature, it became a stable part of CSS and reached baseline widely available support in all major engines. It keeps related selectors together, mirrors the structure of your markup, and removes the need to repeat the parent selector for a whole family of component styles.

The basics

Nesting is simply placing a rule inside another rule so the inner selector is combined with the outer one, in the same way Sass users are already familiar with.

.navigation {
  margin: 1rem;

  ul {
    display: flex;
    gap: 0.5rem;
  }

  a {
    color: inherit;
    text-decoration: none;
  }
}

This compiles to .navigation ul and .navigation a. The nested rules stay grouped with the parent, so you can read the whole component in one block instead of jumping between separate top-level selectors. It works for classes, elements, pseudo-classes, media queries and everything else you would nest.

Because it is a native feature, it runs with no build output, no extra dependency and no risk of a preprocessor mismatch. Where the nesting matches plain CSS, a browser reads it directly.

The ampersand rule

The & symbol refers to the parent selector, and it is the mechanism that keeps nesting general. Consider these two forms:

.card {
  & .title { font-weight: 700; }   /* .card .title */
  &:hover { border-color: blue; }  /* .card:hover */
}

Without the ampersand, a nested selector is implicitly combined with the parent using descendant style. The subtle rule that differs from Sass is about relative and compound selectors: a selector that begins with a type selector, such as h2 or div, is treated as descendant and therefore does not need the ampersand, but a compound selector like .active is interpreted as .card.active, not .card .active. When you want the nested selector to combine with the parent rather than descend from it, you prepend it with &, as in & > .media or & + p.

Getting this distinction right is the most common source of surprise when moving nested Sass styles to native CSS without running them through a build.

Specificity behavior

The important difference from Sass is specificity. A nested rule's specificity is computed by merging the specificities of the selectors as they are written, matching the cascade rules of regular CSS. In practice a nested descendant selector has the same specificity as the flattened selector it represents, so .card .title and its nested equivalent resolve identically.

Where preprocessors differ is that Sass concatenated selectors textually, which could produce an inflated specificity for nested compound selectors. Native CSS follows the ordinary rules instead, with the ampersand handled the way a selector list is handled in :is() for specificity purposes. The practical consequence is that you can reason about nested rules with the same specificity intuition you already use, and you can influence the outcome with cascade layers and specificity rather than relying on how deep you nested.

Native nesting composes cleanly with the rest of modern CSS, so you can nest inside custom properties blocks or nest queries inside a component to keep everything in one place. See css specificity for how the cascade settles ties, and cascade layers for ordering nested groups of rules predictably.

Need a website built, fixed, optimised, migrated or replaced?

This technical resource is written by CSMBAC, a small design and development studio. If you would rather hand the problem to a professional, the website service page explains how we build enquiry-ready websites.

Explore website services