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

Dwie konkurujące ze sobą składnie potrzebują Twojej pomocy w określeniu, która z nich powinna zostać zaproponowana jako kandydat do specyfikacji.

Zagnieżdżanie w CSS to wygodny dodatek do składni, który umożliwia dodawanie CSS wewnątrz zestawu reguł. Jeśli używasz SCSS, Less lub Stylus, z pewnością znasz kilka wersji tego kodu:

.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Po skompilowaniu przez preprocesor do zwykłego CSS wygląda to tak:

.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

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

Oficjalna wersja CSS tej składni jest poważnie rozważana. Mamy jednak rozbieżność opinii, którą chcielibyśmy rozwiązać przy pomocy społeczności. W dalszej części tego posta przedstawimy opcje składni, aby na końcu można było wypełnić ankietę.

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

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

  1. Niejednoznaczne parsowanie
    Niektóre zagnieżdżone selektory mogą wyglądać dokładnie jak właściwości i preprocesory są w stanie je rozwiązać i nimi zarządzać w czasie kompilacji. Silniki przeglądarek nie będą miały tych samych możliwości, więc selektory nigdy nie powinny być interpretowane w sposób nieprecyzyjny.

  2. Konflikty analizowania preprocesora
    Sposób zagnieżdżania w CSS nie powinien powodować problemów z preprocesorami ani z dotychczasowymi procesami zagnieżdżania deweloperów. Byłoby to szkodliwe i lekceważące dla tych ekosystemów i społeczności.

  3. Oczekiwanie na :is()
    Podstawowe zagnieżdżanie nie wymaga :is(), ale bardziej złożone zagnieżdżanie już tak. W przykładzie 3 znajdziesz krótkie wprowadzenie do list selektorów i zagnieżdżania. Wyobraź sobie, że lista selektorów znajduje się w środku selektora, a nie na początku. W takich przypadkach znak :is() jest wymagany do grupowania selektorów w środku innego selektora.

Omówienie tego, co porównujemy

Chcemy, aby zagnieżdżanie CSS działało prawidłowo, dlatego włączamy w ten proces społeczność. W sekcjach poniżej opisujemy 3 możliwe wersje, które oceniamy. Następnie omówimy kilka przykładów użycia, aby je porównać. Na koniec poprosimy Cię o wypełnienie krótkiej ankiety, w której zapytamy, która opcja podobała Ci się najbardziej.

Opcja 1. @nest

Jest to obecnie określona składnia w CSS Nesting 1. Umożliwia wygodne zagnieżdżanie stylów dołączania przez rozpoczynanie nowych zagnieżdżonych selektorów od znaku &. Umożliwia też umieszczanie kontekstu & w dowolnym miejscu nowego selektora, np. gdy nie tylko dodajesz podmioty.@nest Jest elastyczny i minimalistyczny, ale kosztem konieczności zapamiętania @nest lub & w zależności od przypadku użycia.

Opcja 2. @nest restricted

Jest to bardziej rygorystyczna alternatywa, która ma na celu zmniejszenie wspomnianego wcześniej kosztu zapamiętywania dwóch metod zagnieżdżania. Ta ograniczona składnia zezwala na zagnieżdżanie tylko po znaku @nest, więc nie ma wygodnego wzorca tylko dołączania. 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. Nawiasy

Aby uniknąć podwójnej składni lub dodatkowego bałaganu związanego z @nestpropozycjami, Miriam SuzanneElika Etemad zaproponowały alternatywną składnię, która zamiast tego opiera się na dodatkowych nawiasach klamrowych. Zapewnia to przejrzystość składni, dodając tylko 2 dodatkowe znaki i nie wprowadzając nowych reguł @. Umożliwia też grupowanie zagnieżdżonych reguł według wymaganego typu zagnieżdżenia, co upraszcza wiele podobnie zagnieżdżonych selektorów.

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

@nest

.foo {
  color: #111;

  & .bar {
    color: #eee;
  }
}

@nest always

.foo {
  color: #111;

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

nawiasy,

.foo {
  color: #111;

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

Odpowiednik CSS

.foo {
  color: #111;
}

.foo .bar {
  color: #eee;
}

Przykład 2. Złożone zagnieżdżanie

@nest

.foo {
  color: blue;

  &.bar {
    color: red;
  }
}

@nest always

.foo {
  color: blue;

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

nawiasy,

.foo {
  color: blue;

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

Odpowiednik CSS

.foo {
  color: blue;
}

.foo.bar {
  color: red;
}

Przykład 3. Listy 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 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 CSS

figure {
  margin: 0;
}

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

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

Przykład 5. Zagnieżdżanie elementów nadrzędnych lub zmiana 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 CSS

.foo {
  color: red;
}

.parent .foo {
  color: blue;
}

Przykład 6. Łączenie bezpośredniego i nadrzędnego 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 CSS

.foo {
  color: blue;
}

.bar .foo {
  color: red;
}

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

Przykład 7. Zagnieżdżanie zapytań o media

@nest

.foo {
  display: grid;

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

lub wyraźnie / rozszerzone

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

nawiasy,

.foo {
  display: grid;

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

lub wyraźnie / rozszerzone

.foo {
  display: grid;

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

Odpowiednik 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 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 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 to porównanie i przykłady składni, które oceniamy, są dla Ciebie satysfakcjonujące. Zapoznaj się z nimi uważnie i napisz poniżej, które z nich Ci się podobają. Dziękujemy za pomoc w rozwijaniu zagnieżdżania CSS do składni, którą wszyscy poznamy i polubimy.

Wypełnij ankietę