Pomoc dotycząca wyboru składni do zagnieżdżania CSS

Musisz pomóc w wyborze jednej z 2 konkurujących ze sobą składni, która zostanie wybrana jako kandydat na specyfikację.

Adam Argyle
Adam Argyle
Miriam Suzanne
Miriam Suzanne

Zagnieżdżanie CSS to wygodna składnia, która umożliwia dodawanie CSS wewnątrz reguł. Jeśli korzystasz z SCSS, Less lub Stylus, na pewno widziałeś/widziałaś kilka wersji tego:

.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Po skompilowaniu przez preprocesor do zwykłego kodu CSS staje się on zwykłym kodem CSS, np.:

.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

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

Rozważamy oficjalną wersję tej składni w CSS. Mamy rozbieżne preferencje, dlatego chcielibyśmy skorzystać z pomocy społeczności, aby rozstrzygnąć ten spór. W dalszej części tego posta przedstawimy opcje składni, abyś mógł/mogła wypełnić ankietę.

Dlaczego przykład zamieszczony powyżej nie może być składnią zagnieżdżania CSS?

Najpopularniejszej składni zagnieżdżania nie można używać w postaci wyjściowej z kilku powodów:

  1. Niejednoznaczne parsowanie
    Niektóre zagnieżdżone selektory mogą wyglądać dokładnie tak samo jak właściwości i przetwarzacze, które mogą je rozwiązywać i zarządzać nimi w czasie kompilacji. Silniki przeglądarek nie mają tych samych możliwości, dlatego selektory nie mogą być interpretowane luźno.

  2. Konflikty podczas analizowania preprocesora
    Umieszczanie elementów w CSS nie powinno powodować problemów z preprocesorami ani z dotychczasowymi procesami umieszczania elementów przez deweloperów. Byłoby to uciążliwe i nieodpowiedzialne wobec tych ekosystemów i społeczności.

  3. Oczekiwanie na :is()
    Podstawowe zagnieżdżenie nie wymaga :is(), ale bardziej złożone zagnieżdżenie już tak. Aby poznać podstawy selektorów list i ich zagnieżdżania, zapoznaj się z przykładem 3. Załóżmy, że lista selektorów znajdowała się w środku selektora, a nie na początku. W takich przypadkach wymagane jest użycie :is(), aby zgrupować selektory w środku innego selektora.

Omówienie tego, co porównujemy

Chcemy dopracować zagnieżdżanie CSS, dlatego zapraszamy społeczność do udziału w tym procesie. W sekcjach poniżej opisujemy 3 możliwe wersje, które rozważamy. Następnie omówimy kilka przykładów użycia, a na koniec przeprowadzimy krótką ankietę, w której poprosimy Cię o oznaczenie preferowanego rozwiązania.

Opcja 1. @nest

Jest to składnia określona w 1 poziomie zagnieżdżania CSS. Umożliwia wygodne zagnieżdżanie stylów przez dołączanie stylów przez rozpoczęcie nowych zagnieżdżonych selektorów od &. Oferuje też @nest jako sposób na umieszczenie kontekstu & w dowolnym miejscu nowego selektora, na przykład wtedy, gdy nie dołączasz tylko tematów. Jest elastyczny i minimalny, ale wymaga zapamiętania @nest lub & w zależności od przypadku użycia.

Opcja 2. @nest restricted

Jest to surowsza alternatywa, która ma na celu zmniejszenie wspomnianych kosztów związanych z zapamiętywaniem 2 metod zagnieżdżania. Ta ograniczona składnia zezwala na zagnieżdżanie tylko po @nest, więc nie ma w niej wbudowanego wzoru dodawania. Usuwa niejednoznaczność wyboru, tworząc jeden łatwy do zapamiętania sposób zagnieżdżania, ale rezygnuje z zwięzłości na rzecz konwencji.

Opcja 3. W nawiasach

Aby uniknąć podwójnej składni lub dodatkowego zaśmiecania kodu w propozycjach @nest, Miriam SuzanneElika Etemad zaproponowały alternatywną składnię, która zamiast dodatkowych nawiasów klamrowych opiera się na dodatkowych nawiasach klamrowych. Zapewnia to przejrzystość składni przy użyciu zaledwie 2 dodatkowych znaków i bez nowych reguł at. Umożliwia też grupowanie zagnieżdżonych reguł według typu zagnieżdżenia, co upraszcza stosowanie wielu podobnie zagnieżdżonych selektorów.

Przykład 1. Bezpośrednie zagnieżdżenie

@nest

.foo {
  color: #111;

  & .bar {
    color: #eee;
  }
}

@nest always

.foo {
  color: #111;

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

nawiasy

.foo {
  color: #111;

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

Odpowiednik kodu CSS

.foo {
  color: #111;
}

.foo .bar {
  color: #eee;
}

Przykład 2. Zagnieżdżanie złożonych elementów

@nest

.foo {
  color: blue;

  &.bar {
    color: red;
  }
}

@nest always

.foo {
  color: blue;

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

nawiasy

.foo {
  color: blue;

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

Odpowiednik kodu CSS

.foo {
  color: blue;
}

.foo.bar {
  color: red;
}

Przykład 3. Lista selektorów i zagnieżdżanie

@nest

.foo, .bar {
  color: blue;

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

@nest always

.foo, .bar {
  color: blue;

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

nawiasy

.foo, .bar {
  color: blue;

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

Odpowiednik kodu CSS

.foo, .bar {
  color: blue;
}

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

Przykład 4. Wiele poziomów

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

nawiasy

figure {
  margin: 0;

  {
    & > figcaption {
      background: lightgray;

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

Odpowiednik kodu CSS

figure {
  margin: 0;
}

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

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

Przykład 5. Zmiana zagnieżżenia elementu nadrzędnego lub tematu

@nest

.foo {
  color: red;

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

@nest always

.foo {
  color: red;

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

nawiasy

.foo {
  color: red;

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

Odpowiednik kodu CSS

.foo {
  color: red;
}

.parent .foo {
  color: blue;
}

Przykład 6. Mieszanie zagnieżdżania bezpośredniego i zagnieżdżania nadrzędnego

@nest

.foo {
  color: blue;

  @nest .bar & {
    color: red;

    &.baz {
      color: green;
    }
  }
}

@nest always

.foo {
  color: blue;

  @nest .bar & {
    color: red;

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

nawiasy

.foo {
  color: blue;

  {
    .bar & {
      color: red;

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

Odpowiednik kodu CSS

.foo {
  color: blue;
}

.bar .foo {
  color: red;
}

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

Przykład 7. Zagnieżdżanie zapytania dotyczącego multimediów

@nest

.foo {
  display: grid;

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

lub w sposób wyraźny / rozszerzony

.foo {
  display: grid;

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

@nest zawsze (zawsze jawnie)

.foo {
  display: grid;

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

nawiasy

.foo {
  display: grid;

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

lub w sposób wyraźny / rozszerzony

.foo {
  display: grid;

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

Odpowiednik kodu CSS

.foo {
  display: grid;
}

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

Przykład 8. Zagnieżdżanie grup

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

nawiasy

fieldset {
  border-radius: 10px;

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

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

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

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

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

Przykład 9. Złożona grupa zagnieżdżona „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;
  }
}

nawiasy

dialog {
  border: none;

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

    & > form {
      display: grid;

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

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

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

Czas na głosowanie

Mamy nadzieję, że uważasz, że było to sprawiedliwe porównanie i próbka opcji składniowych, które obecnie analizujemy. Zapoznaj się z nimi uważnie i podaj poniżej, którą wersję wolisz. Dziękujemy za pomoc w ulepszeniu zagnieżdżania CSS do składni, którą wszyscy poznamy i pokochamy.

Wypełnij ankietę