& / nested selectors

CSS Nesting

Sass and Less popularised writing selectors inside selectors; CSS finally does it natively. No compiler, no source maps, just a smaller diff between the CSS you write and the CSS the browser parses.

The CSS

.card {
  border: 1px solid var(--border);
  transition: transform 0.15s, border-color 0.15s;

  &:hover {
    transform: translateY(-2px);
    border-color: var(--text-secondary);
  }

  &.featured {
    border-color: var(--accent);
  }

  &[data-variant="neutral"] {
    --accent: var(--text-secondary);
  }

  &[data-variant="success"] {
    --accent: var(--success);
  }

  & button {
    background: var(--accent);

    &:hover:not(:disabled) { opacity: 0.85; }
    &:disabled { opacity: 0.4; cursor: not-allowed; }
  }
}

How it works

Any rule can contain another rule. Nested selectors that start with a type selector need an explicit & (CSS can’t otherwise tell a nested rule from a declaration), but class, pseudo-class, and attribute selectors nest directly.

& stands in for the parent selector, so &:hover, &.featured, and &[data-variant="success"] all read as “this element, when…”. At-rules nest too, so a media query for a component can live right next to the rest of its styles instead of in a separate block at the bottom of the file.

All evergreen browsers (Chrome/Edge 112+, Safari 16.5+, Firefox 117+)