The future of CSS: Nesting Selectors

Early March the first Editor’s Draft for the CSS Nesting Module was published. The draft outlines a future mechanism by which we’ll be able to nest CSS selectors natively (e.g. in pure CSS, without the use of any preprocessors)

This module describes support for nesting a style rule within another style rule, allowing the inner rule’s selector to reference the elements matched by the outer rule. This feature allows related styles to be aggregated into a single structure within the CSS document, improving readability and maintainability.

🤔 Editor's Draft?

A Editor's Draft (ED) is an unofficial version of a specification. They have no official standing, and do not necessarily imply consensus of the CSS Working Group. These Editor's Drafts can describe modules that are not part of the Recommendation Track yet, or can contain in-progress versions of Modules that already are part of the Rec Track.

If an Editor's Draft gets picked up by the CSSWG, a “First Public Working Draft” gets published. This makes the Module officially part of the Rec Track and marks the start of the Working Draft (WD) phase. From there on the proposal can advance further down the Recommendation Track.

In visual form, the Recommendation Track looks something like this:

See An Inside View of the CSS Working Group at W3C for more details on all phases.

UPDATE 2021.07.07: 🥳 The CSSWG has agreed to publish the First Public Working Draft of this module, making it part of the Recommendation Track! Things are getting official, folks!

UPDATE 2021.08.31: The First Public Working Draft got published.

~

Direct nesting with the & selector

Using the & selector (read this as “the nesting selector”), you can refer to the selector from the parent rule.

Instead of writing this …

table.colortable td {
  text-align:center;
}
table.colortable td.c {
  text-transform:uppercase;
}
table.colortable td:first-child, table.colortable td:first-child+td {
  border:1px solid black;
}
table.colortable th {
  text-align:center;
  background:black;
  color:white;
}

… you can write this thanks to CSS Nesting:

table.colortable {
  & td {
    text-align: center;
    &.c { text-transform: uppercase }
    &:first-child, &:first-child + td { border: 1px solid black }
  }
  & th {
    text-align: center;
    background: black;
    color: white;
  }
}

Cool! 😎

~

Caveats

The & selector is mandatory when nesting

When nesting in CSS, you always need to use the & selector. So you won’t be able to do this:

/* INVALID, missing & */
.foo {
  .bar {
    color: hotpink;
  }
}

The fix would be to write & .bar instead of .bar

Declarations must become before nesting selectors

If the outer selector also contains some CSS properties, they must go before the nesting selector-part. In the example below the rules after the inner selector will simply be ignored:

.foo {
  background: lime;
  & .bar {
    color: hotpink;
  }
  font-weight: 700; /* INVALID, should go before “& .bar” */
}

The fix would be to place the font-weight: 700; declaration before the & .bar block.

The & selector must be the first compound selector when direct nesting

The & selector can also only be used when it’s first compound selector (e.g. it appears at the first position) of an inner selector.

/* INVALID, & should come first */
.foo {
  .bar & {
    color: hotpink;
  }
}

The fix would be to use an alternative syntax (see further down)

💡 This requirement is put in place so that the parse can unambiguously determine what we’re talking about. As explained in the spec:

The syntax of a selector overlaps with the syntax of a declaration. For example, if a parser starts by seeing color:hover, it can’t tell whether that’s the color property (being set to an invalid value…) or a selector for a <color> element.

Makes sense.

~

An alternative syntax: the @nest rule

To cater for that second caveat, you can to use the @nest rule syntax, which is more lax. It still requires a & selector, but the selector does not need to appear first:

/* VALID */
.foo {
  @nest .bar & {
    color: hotpink;
  }
}

Aside from the slight difference in how they’re written, both the @nest rule and “direct nesting” are exactly equivalent in functionality.

~

Browser Support

Don’t expect this to land in browsers any time soon. Right now bugs have been filed, but no actual work has been done on it:

~

🔥 Like what you see? Want to stay in the loop? Here's how:

About the author

Bramus is a Freelance Web Developer from Belgium. From the moment he discovered view-source at the age of 14 (way back in 1997), he fell in love with the web and has been tinkering with it ever since (more …)

Join the Conversation

1 Comment

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.