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ę.

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ę zwykłym kodem CSS, na przykład:

.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
    Sposób zagnieżdżania w CSS nie powinien powodować problemów z preprocesorami ani z dotychczasowymi procesami zagnieżdżania 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 następnych sekcjach 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 ocena, która opcja podoba Ci się najbardziej.

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 dodawanie nowych zagnieżdżonych selektorów z wartością &. 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 wzorca dołączania tylko w celu wygody. Usuwamy niejednoznaczność wyboru, tworząc jeden łatwy do zapamiętania sposób zagnieżdżania, ale rezygnujemy 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 obsługę 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 jawny / 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 jawny / 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ę