https://developer.chrome.com/blog/help-css-nesting/ Skip to content Home Docs Blog Articles Home Docs Blog Articles Blog A bird nest with a couple of blue eggs inside, surrounded by lush greenery. Help pick a syntax for CSS nesting Two competing syntaxes need your help in determining which should be championed through to a specification candidate. Published on Tuesday, July 26, 2022 Adam Argyle Adam Argyle Developer Relations Engineer working on Chrome CSS, UI, & DevTools. Miriam Suzanne Miriam Suzanne Co-Founder of OddBird and CSS Working Group Invited Expert Table of contents * Overview of what we're comparing + Option 1: @nest + Option 2: @nest restricted + Option 3: Brackets * Example 1 - Direct nesting + @nest + @nest always + brackets + Equivalent CSS * Example 2 - Compound nesting + @nest + @nest always + brackets + Equivalent CSS * Example 3 - Selector lists and nesting + @nest + @nest always + brackets + Equivalent CSS * Example 4 - Multiple levels + @nest + @nest always + brackets + Equivalent CSS * Example 5 - Parent nesting or subject changing + @nest + @nest always + brackets + Equivalent CSS * Example 6 - Mixing direct and parent nesting + @nest + @nest always + brackets + Equivalent CSS * Example 7 - Media query nesting + @nest + @nest always (is always explicit) + brackets + Equivalent CSS * Example 8 - Nesting groups + @nest + @nest always + brackets + Equivalent CSS * Example 9 - Complex nesting group "Kitchen Sink" + @nest + @nest always + brackets + Equivalent CSS * Time to vote CSS nesting is a convenience syntax addition that allows CSS to be added inside of a ruleset. If you've used SCSS, Less or Stylus, then you've most certainly seen a few flavors of this: .nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } } Which after being compiled to regular CSS by the preprocessor, turns into regular CSS like this: .nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; } An official CSS version of this syntax is being strongly considered and we have a split in preference that we'd like to employ the help of the community to break the tie. The rest of this post will be introducing the syntax options so you can feel informed to take a survey at the end. Why can't the exact nesting example shown above be the syntax for CSS nesting? There are a few reasons the most popular nesting syntax can't be used as is: 1. Ambiguous parsing Some nested selectors can look exactly like properties and preprocessors are able to resolve and manage them at build time. Browser engines won't have the same affordances, selectors needs to never be loosely interpreted. 2. Preprocessor parsing conflicts The CSS way of nesting shouldn't break preprocessors or existing developer nesting workflows. This would be disruptive and inconsiderate to those ecosystems and communities. 3. Waiting for :is() Basic nesting doesn't need :is() but more complex nesting does. See Example #3 for a light introduction to selector lists and nesting. Imagine that selector list was in the middle of a selector instead of at the beginning, in those cases :is() is required in order to group the selectors in the middle of another selector. # Overview of what we're comparing We want to get CSS nesting right, and in that spirit we're including the community. The following sections will help describe the three possible versions we're evaluating. We'll then go over some examples of usage for comparison, and at the end there will be a light survey asking you which you preferred overall. # Option 1: @nest This is the current specified syntax in CSS Nesting 1. It offers a convenient way to nest appending styles by starting new nested selectors with &. It also offers @nest as a way to place the & context anywhere inside a new selector, like when you're not just appending subjects. It's flexible and minimal but at the expense of needing to remember @nest or & depending on your use case. # Option 2: @nest restricted This is a stricter alternative, in an attempt to reduce the expense mentioned of remembering two nesting methods. This restricted syntax only allows nesting to occur following @nest, so there's no append only convenience pattern. Removing ambiguity of choice, creating one easy to remember way to nest, but sacrifices terseness in favor of convention. It's worth noting that the less restricted @nest syntax (Option 1) could use a linter to enforce a usage rule across a team, in case they together decided they didn't like the ambiguity or terseness. Changing the spec may be an extreme measure. # Option 3: Brackets In order to avoid the double-syntax or extra clutter involved with the @nest proposals, Miriam Suzanne and Elika Etemad proposed an alternative syntax that instead relies on additional curly-brackets. This provides syntax clarity, with only two extra characters, and no new at-rules. It also allows nested rules to be grouped by the type of nesting required, as a way of simplifying multiple similarly nested selectors. # Example 1 - Direct nesting # @nest .foo { color: #111; & .bar { color: #eee; } } # @nest always .foo { color: #111; @nest & .bar { color: #eee; } } # brackets .foo { color: #111; { & .bar { color: #eee; } } } # Equivalent CSS .foo { color: #111; } .foo .bar { color: #eee; } # Example 2 - Compound nesting # @nest .foo { color: blue; &.bar { color: red; } } # @nest always .foo { color: blue; @nest &.bar { color: red; } } # brackets .foo { color: blue; { &.bar { color: red; } } } # Equivalent CSS .foo { color: blue; } .foo.bar { color: red; } # Example 3 - Selector lists and nesting # @nest .foo, .bar { color: blue; & + .baz, &.qux { color: red; } } # @nest always .foo, .bar { color: blue; @nest & + .baz, &.qux { color: red; } } # brackets .foo, .bar { color: blue; { & + .baz, &.qux { color: red; } } } # Equivalent CSS .foo, .bar { color: blue; } :is(.foo, .bar) + .baz, :is(.foo, .bar).qux { color: red; } # Example 4 - Multiple levels # @nest figure { margin: 0; & > figcaption { background: lightgray; & > p { font-size: .9rem; } } } # @nest always figure { margin: 0; @nest & > figcaption { background: lightgray; @nest & > p { font-size: .9rem; } } } # brackets figure { margin: 0; { & > figcaption { background: lightgray; { & > p { font-size: .9rem; } } } } } # Equivalent CSS figure { margin: 0; } figure > figcaption { background: hsl(0 0% 0% / 50%); } figure > figcaption > p { font-size: .9rem; } # Example 5 - Parent nesting or subject changing # @nest .foo { color: red; @nest .parent & { color: blue; } } # @nest always .foo { color: red; @nest .parent & { color: blue; } } # brackets .foo { color: red; { .parent & { color: blue; } } } # Equivalent CSS .foo { color: red; } .parent .foo { color: blue; } # Example 6 - Mixing direct and parent nesting # @nest .foo { color: blue; @nest .bar & { color: red; &.baz { color: green; } } } # @nest always .foo { color: blue; @nest .bar & { color: red; @nest &.baz { color: green; } } } # brackets .foo { color: blue; { .bar & { color: red; { &.baz { color: green; } } } } } # Equivalent CSS .foo { color: blue; } .bar .foo { color: red; } .bar .foo.baz { color: green; } # Example 7 - Media query nesting # @nest .foo { display: grid; @media (width => 30em) { grid-auto-flow: column; } } # or explicitly / extended .foo { display: grid; @media (width => 30em) { & { grid-auto-flow: column; } } } # @nest always (is always explicit) .foo { display: grid; @media (width => 30em) { @nest & { grid-auto-flow: column; } } } # brackets .foo { display: grid; @media (width => 30em) { grid-auto-flow: column; } } # or explicitly / extended .foo { display: grid; @media (width => 30em) { & { grid-auto-flow: column; } } } # Equivalent CSS .foo { display: grid; } @media (width => 30em) { .foo { grid-auto-flow: column; } } There's a convenience syntax called implicit nesting. The top/first examples in each example show the implicit nesting feature, where the scope of the style rules are applied to the implicit selector scope they are nested within. Implicit nesting does need adjusting when more than one nested selector needs to exist, at which point you'll need to refactor to the explicit nesting style. # Example 8 - Nesting groups # @nest fieldset { border-radius: 10px; &:focus-within { border-color: hotpink; } & > legend { font-size: .9em; } & > div { & + div { margin-block-start: 2ch; } & > label { line-height: 1.5; } } } # @nest always fieldset { border-radius: 10px; @nest &:focus-within { border-color: hotpink; } @nest & > legend { font-size: .9em; } @nest & > div { @nest & + div { margin-block-start: 2ch; } @nest & > label { line-height: 1.5; } } } # brackets fieldset { border-radius: 10px; { &:focus-within { border-color: hotpink; } } > { legend { font-size: .9em; } div {{ + div { margin-block-start: 2ch; } > label { line-height: 1.5; } }} } } # Equivalent CSS fieldset { border-radius: 10px; } fieldset:focus-within { border-color: hotpink; } fieldset > legend { font-size: .9em; } fieldset > div + div { margin-block-start: 2ch; } fieldset > div > label { line-height: 1.5; } # Example 9 - Complex nesting group "Kitchen Sink" # @nest dialog { border: none; &::backdrop { backdrop-filter: blur(25px); } & > form { display: grid; & > :is(header, footer) { align-items: flex-start; } } @nest html:has(&[open]) { overflow: hidden; } } # @nest always dialog { border: none; @nest &::backdrop { backdrop-filter: blur(25px); } @nest & > form { display: grid; @nest & > :is(header, footer) { align-items: flex-start; } } @nest html:has(&[open]) { overflow: hidden; } } # brackets dialog { border: none; { &::backdrop { backdrop-filter: blur(25px); } & > form { display: grid; { & > :is(header, footer) { align-items: flex-start; } } } } { html:has(&[open]) { overflow: hidden; } } } # Equivalent CSS dialog { border: none; } dialog::backdrop { backdrop-filter: blur(25px); } dialog > form { display: grid; } dialog > form > :is(header, footer) { align-items: flex-start; } html:has(dialog[open]) { overflow: hidden; } # Time to vote Hopefully you feel that was a fair comparison and sample platter of the syntax options we're evaluating. Please review them carefully and let us know which you prefer below. We appreciate you helping us advance CSS nesting to a syntax we all will come to know and love! Take the survey! CSS Last updated: Tuesday, July 26, 2022 * Improve article Table of contents * Overview of what we're comparing + Option 1: @nest + Option 2: @nest restricted + Option 3: Brackets * Example 1 - Direct nesting + @nest + @nest always + brackets + Equivalent CSS * Example 2 - Compound nesting + @nest + @nest always + brackets + Equivalent CSS * Example 3 - Selector lists and nesting + @nest + @nest always + brackets + Equivalent CSS * Example 4 - Multiple levels + @nest + @nest always + brackets + Equivalent CSS * Example 5 - Parent nesting or subject changing + @nest + @nest always + brackets + Equivalent CSS * Example 6 - Mixing direct and parent nesting + @nest + @nest always + brackets + Equivalent CSS * Example 7 - Media query nesting + @nest + @nest always (is always explicit) + brackets + Equivalent CSS * Example 8 - Nesting groups + @nest + @nest always + brackets + Equivalent CSS * Example 9 - Complex nesting group "Kitchen Sink" + @nest + @nest always + brackets + Equivalent CSS * Time to vote Follow us Contribute * File a bug * View source Related content * web.dev * Web Fundamentals * Case studies * Podcasts Connect * Twitter * YouTube * GitHub Chrome Firebase All products Privacy Terms Content available under the CC-BY-SA-4.0 license We serve cookies on this site to analyze traffic, remember your preferences, and optimize your experience. More details Ok, Got it.