Hilfe beim Auswählen einer Syntax für die CSS-Verschachtelung

Es gibt zwei konkurrierende Syntaxen, bei denen wir Ihre Hilfe benötigen, um zu entscheiden, welche bis zum Spezifikationskandidaten weitergeführt werden soll.

CSS-Nesting ist eine praktische Syntaxerweiterung, mit der CSS in einem Regelsatz hinzugefügt werden kann. Wenn Sie SCSS, Less oder Stylus verwendet haben, haben Sie sicher schon einige Varianten davon gesehen:

.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Nach der Kompilierung in reguläres CSS durch den Präprozessor sieht das so aus:

.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

Eine offizielle CSS-Version dieser Syntax wird in Erwägung gezogen. Wir haben eine Meinungsverschiedenheit, die wir mithilfe der Community ausräumen möchten. Im weiteren Verlauf dieses Beitrags werden die Syntaxoptionen vorgestellt, damit Sie am Ende eine fundierte Entscheidung treffen können.

Warum kann das oben gezeigte Beispiel für die genaue Verschachtelung nicht die Syntax für die CSS-Verschachtelung sein?

Es gibt einige Gründe, warum die beliebteste Verschachtelungssyntax nicht direkt verwendet werden kann:

  1. Mehrdeutige Analyse
    Einige verschachtelte Selektoren können genau wie Eigenschaften und Präprozessoren aussehen und werden zur Build-Zeit aufgelöst und verwaltet. Browser-Engines haben nicht dieselben Möglichkeiten. Selektoren dürfen daher nie lose interpretiert werden.

  2. Konflikte beim Parsen von Präprozessoren
    Die CSS-Methode zum Verschachteln sollte keine Präprozessoren oder vorhandene Verschachtelungs-Workflows von Entwicklern beeinträchtigen. Das wäre störend und rücksichtslos gegenüber diesen Ökosystemen und Communities.

  3. Warten auf :is()
    Für die einfache Verschachtelung ist :is() nicht erforderlich, für komplexere Verschachtelungen jedoch schon. Beispiel 3 bietet eine kurze Einführung in Selektorlisten und das Verschachteln. Stellen Sie sich vor, die Selektorliste befände sich in der Mitte eines Selektors anstatt am Anfang. In diesen Fällen ist :is() erforderlich, um die Selektoren in der Mitte eines anderen Selektors zu gruppieren.

Übersicht der Vergleichspunkte

Wir möchten, dass CSS-Nesting richtig funktioniert, und beziehen deshalb die Community mit ein. In den folgenden Abschnitten werden die drei möglichen Versionen beschrieben, die wir prüfen. Anschließend werden wir einige Beispiele für die Verwendung zum Vergleich durchgehen. Am Ende gibt es eine kurze Umfrage, in der Sie gefragt werden, welche Sie insgesamt bevorzugt haben.

Option 1: @nest

Dies ist die aktuelle angegebene Syntax in CSS Nesting 1. So können Sie Anhängestile bequem verschachteln, indem Sie neue verschachtelte Selektoren mit & beginnen. Außerdem bietet es @nest als Möglichkeit, den &-Kontext an einer beliebigen Stelle in einem neuen Selektor zu platzieren, z. B. wenn Sie nicht nur Themen anhängen. Es ist flexibel und minimal, aber Sie müssen sich je nach Anwendungsfall @nest oder & merken.

Option 2: @nest restricted

Dies ist eine strengere Alternative, die darauf abzielt, die oben erwähnten Kosten für das Merken von zwei Verschachtelungsmethoden zu senken. Diese eingeschränkte Syntax erlaubt nur das Verschachteln nach @nest. Es gibt also kein praktisches Muster für das Anhängen. Durch die Entfernung von Mehrdeutigkeiten bei der Auswahl wird eine leicht zu merkende Möglichkeit zum Verschachteln geschaffen, die jedoch die Kürze zugunsten der Konvention opfert.

Option 3: Klammern

Um die Doppelsyntax oder das zusätzliche Durcheinander der @nest-Vorschläge zu vermeiden, schlugen Miriam Suzanne und Elika Etemad eine alternative Syntax vor, die stattdessen auf zusätzlichen geschweiften Klammern basiert. Das sorgt für eine übersichtliche Syntax mit nur zwei zusätzlichen Zeichen und ohne neue @-Regeln. Außerdem können verschachtelte Regeln nach der Art der erforderlichen Verschachtelung gruppiert werden, um mehrere ähnlich verschachtelte Selektoren zu vereinfachen.

Beispiel 1: Direkte Verschachtelung

@nest

.foo {
  color: #111;

  & .bar {
    color: #eee;
  }
}

@nest always

.foo {
  color: #111;

  @nest & .bar {
    color: #eee;
  }
}

Klammern

.foo {
  color: #111;

  {
    & .bar {
      color: #eee;
    }
  }
}

Entsprechender CSS-Code

.foo {
  color: #111;
}

.foo .bar {
  color: #eee;
}

Beispiel 2: Verschachtelung von zusammengesetzten Begriffen

@nest

.foo {
  color: blue;

  &.bar {
    color: red;
  }
}

@nest always

.foo {
  color: blue;

  @nest &.bar {
    color: red;
  }
}

Klammern

.foo {
  color: blue;

  {
    &.bar {
      color: red;
    }
  }
}

Entsprechender CSS-Code

.foo {
  color: blue;
}

.foo.bar {
  color: red;
}

Beispiel 3: Selektorlisten und Verschachtelung

@nest

.foo, .bar {
  color: blue;

  & + .baz,
  &.qux {
    color: red;
  }
}

@nest always

.foo, .bar {
  color: blue;

  @nest & + .baz,
  &.qux {
    color: red;
  }
}

Klammern

.foo, .bar {
  color: blue;

  {
    & + .baz,
    &.qux {
      color: red;
    }
  }
}

Entsprechender CSS-Code

.foo, .bar {
  color: blue;
}

:is(.foo, .bar) + .baz,
:is(.foo, .bar).qux {
  color: red;
}

Beispiel 4: Mehrere Ebenen

@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;
    }
  }
}

Klammern

figure {
  margin: 0;

  {
    & > figcaption {
      background: lightgray;

      {
        & > p {
          font-size: .9rem;
        }
      }
    }
  }
}

Entsprechender CSS-Code

figure {
  margin: 0;
}

figure > figcaption {
  background: hsl(0 0% 0% / 50%);
}

figure > figcaption > p {
  font-size: .9rem;
}

Beispiel 5: Übergeordnete Verschachtelung oder Themenwechsel

@nest

.foo {
  color: red;

  @nest .parent & {
    color: blue;
  }
}

@nest always

.foo {
  color: red;

  @nest .parent & {
    color: blue;
  }
}

Klammern

.foo {
  color: red;

  {
    .parent & {
      color: blue;
    }
  }
}

Entsprechender CSS-Code

.foo {
  color: red;
}

.parent .foo {
  color: blue;
}

Beispiel 6: Direkte und übergeordnete Verschachtelung kombinieren

@nest

.foo {
  color: blue;

  @nest .bar & {
    color: red;

    &.baz {
      color: green;
    }
  }
}

@nest always

.foo {
  color: blue;

  @nest .bar & {
    color: red;

    @nest &.baz {
      color: green;
    }
  }
}

Klammern

.foo {
  color: blue;

  {
    .bar & {
      color: red;

      {
        &.baz {
          color: green;
        }
      }
    }
  }
}

Entsprechender CSS-Code

.foo {
  color: blue;
}

.bar .foo {
  color: red;
}

.bar .foo.baz {
  color: green;
}

Beispiel 7: Media-Query-Nesting

@nest

.foo {
  display: grid;

  @media (width => 30em) {
    grid-auto-flow: column;
  }
}

oder explizit / erweitert

.foo {
  display: grid;

  @media (width => 30em) {
    & {
      grid-auto-flow: column;
    }
  }
}

@nest always (ist immer explizit)

.foo {
  display: grid;

  @media (width => 30em) {
    @nest & {
      grid-auto-flow: column;
    }
  }
}

Klammern

.foo {
  display: grid;

  @media (width => 30em) {
    grid-auto-flow: column;
  }
}

oder explizit / erweitert

.foo {
  display: grid;

  @media (width => 30em) {
    & {
      grid-auto-flow: column;
    }
  }
}

Entsprechender CSS-Code

.foo {
  display: grid;
}

@media (width => 30em) {
  .foo {
    grid-auto-flow: column;
  }
}

Beispiel 8: Gruppen verschachteln

@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;
    }
  }
}

Klammern

fieldset {
  border-radius: 10px;

  {
    &:focus-within {
      border-color: hotpink;
    }
  }

  > {
    legend {
      font-size: .9em;
    }

    div {
      + div {
        margin-block-start: 2ch;
      }

      > label {
        line-height: 1.5;
      }
    }}
  }
}

Entsprechender CSS-Code

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;
}

Beispiel 9: Komplexe Verschachtelungsgruppe „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;
  }
}

Klammern

dialog {
  border: none;

  {
    &::backdrop {
      backdrop-filter: blur(25px);
    }

    & > form {
      display: grid;

      {
        & > :is(header, footer) {
          align-items: flex-start;
        }
      }
    }
  }

  {
    html:has(&[open]) {
      overflow: hidden;
    }
  }
}

Entsprechender CSS-Code

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;
}

Zeit für die Stimmabgabe

Wir hoffen, dass Sie diesen Vergleich und die Beispiele für die Syntaxoptionen, die wir prüfen, für fair halten. Bitte sehen Sie sich die Vorschläge genau an und teilen Sie uns unten mit, welcher Ihnen am besten gefällt. Vielen Dank, dass Sie uns dabei helfen, CSS-Nesting zu einer Syntax weiterzuentwickeln, die wir alle kennen und lieben werden.

Zur Umfrage