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 powinna zostać wybrana jako kandydat do specyfikacji.

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
    Sposób zagnieżdżania w CSS nie powinien powodować problemów z preprocesorami ani z dotychczasowymi przepływami pracy dotyczącymi zagnieżdżania. 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 elementu :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 końcu 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 w niej wzorca dołączania tylko w celu wygody. 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 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żenie złożone

@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 bezpośredniego i rodzinnego zagnieżdżania

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