CSS: nesting selector (ampersand &)

By Xah Lee. Date: . Last updated: .

What is CSS nesting syntax

Browser support

CSS nesting syntax is widely supported since 2024. It was introduced in 2019.

Basic Nesting Example

/* nested syntax */

.card {
 background-color: pink;
 border: solid 1px grey;

 h2 {
  color: red;
 }

 p {
  color: blue;
 }
}

/* is equivalent to */

.card {
 background-color: pink;
 border: solid 1px grey;
}

.card h2 {
 color: red;
}

.card p {
 color: blue;
}

Nesting syntax

by default, the relation of parent selector and its children have the same meaning as descendant selector.

.aa {
 .bb {
  color: red;
 }
}

/* is converted by CSS compiler to */

.aa .bb {
 color: red;
}

you can override the relation by prepending the combinator operator to the child selector, such as >, +, ~ .

.aa {
 > .bb {
  color: red;
 }
}

/* is converted by CSS compiler to */

.aa > .bb {
 color: red;
}

Ampersand (&), the Nesting Selector

The ampersand & is called Nesting Selector.

when appearing inside nesting, & represents the parent selector.

If used outside nesting, it represents the scoping root :scope (usually selects the Root Element).

you can place & inside the nesting syntax, anywhere where selectors are allowed.

you especially need it when you want to modify the parent selector, such as such as

Example. pseudo-class

.card {
 &:hover {
  color: red;
 }
}

/* is equivalent to */

.card:hover {
 color: red;
}

Example. Multiple nesting selector

.x {
 & > & > & {
  color: red;
 }
}

/* is equivalent to */

.x > .x > .x {
 color: red;
}

Example. Relationship selectors

ul.xflow {
 li {
  /* ampersand UNNECESSARY */
  & > a {
   display: block;
  }
 }
}

/* is equivalent to */

ul.xflow li > a {
 display: block;
}
main {
 /* ampersand is UNNECESSARY in all cases below. */

 /* direct child */
 & > .content {
  color: red;
 }

 /* adjacent sibling */
 & + .sidebar {
  color: red;
 }

 /* subsequent sibling */
 & ~ .footer {
  color: red;
 }
}
main {
 /* descendant (space). ampersand UNNECESSARY. */
 & .title {
  color: red;
 }
}

Example. Appended nesting selector (reverse parent/child)

πŸ›‘ WARNING: nesting syntax does not always mean the outer selector is parent. The ampersand & symbol can be placed in different positions to create many many different relationships. (see below)

/* Example. of reverse parent/child */

h2 {
 section > & {
  color: red;
 }
}

/* is equivalent to */

/* select the header title h2 only if it is direct child of section */
section > h2 {
 color: red;
}

Examples

Multiple classes

/* Multiple classes */

.aa {
 &.bb {
  color: red;
 }
}

/* is equivalent to */

.aa.bb {
 color: red;
}

Pseudo-elements

/* Pseudo-elements  */

.aa {
 &::before {
  content: "β˜…";
 }
}

/* is equivalent to */

.aa::before {
 content: "β˜…";
}

Attribute selectors

/* Attribute selectors */

.aa {
 &[data-accessed] {
  color: red;
 }
}

/* is equivalent to */

.aa[data-accessed] {
 color: red;
}

Nesting media query inside code block

when media query at-rule is nested inside a code block,

tag { rule; @media condition {rules} }

it means, apply the media query styles to the parent selector, when the media query condition is true.

nesting media query is great for grouping selector rules together.

p {
 font-size: 1rem;

 @media (min-width: 768px) {
  font-size: 1.1rem;
 }
}

/* is equivalent to */

p {
 font-size: 1rem;
}

@media (min-width: 768px) {
 p {
  font-size: 1.1rem;
 }
}

CSS, Selectors

Selector types
Simple selectors
Combinators
Selector list
Special selector
Misc

CSS, misc, advanced