Zagnieżdżanie CSS

Jedną z naszych ulubionych funkcji wstępnego przetwarzania danych CSS jest teraz wbudowana w języku: zagnieżdżanie reguł stylu.

Adam Argyle
Adam Argyle

Przed zagnieżdżeniem każdy selektor musiał zostać jawnie zadeklarowany, niezależnie od i otwierać przed sobą nawzajem. Prowadzi to do powtórzeń, zbiorczych arkuszy stylów i rozproszenia błędów podczas tworzenia. z myślą o użytkownikach.

Przed
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

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

Po zagnieżdżeniu selektory można i powiązane z nim reguły stylu.

Po
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

Spróbuj to zrobić w przeglądarce

Zagnieżdżanie pomaga programistom, bo ogranicza konieczność powtarzania selektorów, a jednocześnie pomaga colokalizowania reguł stylu dla powiązanych elementów. Ułatwia to też dopasowanie stylów kod HTML, na który są kierowane. Jeśli komponent .nesting w poprzednim przykładzie to usunięte z projektu, można usunąć całą grupę, zamiast wyszukiwać plików powiązanych instancji selektora.

Nesting może pomóc w tych kwestiach: - organizacja, – Zmniejszenie rozmiaru pliku - Refaktoryzacja

Zagnieżdżanie jest dostępne w Chrome 112, a także w Safari Technical Preview 162.

Pierwsze kroki z zagnieżdżaniem w CSS

W pozostałej części tego posta udostępniamy Ci piaskownicę demonstracyjną,która pomoże Ci zwizualizować wybory. W tym stanie domyślnym nic nie jest zaznaczone wszystko jest widoczne. Wybierając różne kształty i rozmiary, poćwicz jej składnię i zobacz, jak to wygląda w praktyce.

Kolorowa siatka małych i dużych okręgów, trójkątów i kwadratów.

W piaskownicy znajdują się okręgi, trójkąty i kwadraty. Niektóre są małe, średnie czy duży rozmiar. Inne są w kolorze niebieskim, różowym lub fioletowym. Wszystkie znajdują się w: .demo zawierającym element. Poniżej znajduje się podgląd elementów HTML, z których będziesz korzystać kierowania reklam.

<div class="demo">
  <div class="sm triangle pink"></div>
  <div class="sm triangle blue"></div>
  <div class="square blue"></div>
  <div class="sm square pink"></div>
  <div class="sm square blue"></div>
  <div class="circle pink"></div>
  …
</div>

Przykłady zagnieżdżania

Zagnieżdżanie CSS pozwala definiować style elementu w kontekście lub inny selektor.

.parent {
  color: blue;

  .child {
    color: red;
  }
}

W tym przykładzie selektor klasy .child jest umieszczony w obrębie za pomocą selektora klasy .parent. Oznacza to, że zagnieżdżony selektor .child będzie mają zastosowanie tylko do elementów podrzędnych elementów z klasą .parent.

Ten przykład można również zapisać za pomocą symbolu &, aby wskazują, gdzie należy umieścić klasę nadrzędną.

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

Te 2 przykłady są równoważne pod względem funkcjonalnym, a dodatkowo masz różne możliwości, w miarę analizowania bardziej zaawansowanych przykładów z tego artykułu.

Zaznaczanie kręgów

W pierwszym przykładzie chodzi o dodanie stylów do zanikania i zamazywania tylko wewnątrz prezentacji.

Bez zagnieżdżania obecnie CSS:

.demo .circle {
  opacity: .25;
  filter: blur(25px);
}

W przypadku zagnieżdżania można to zrobić na 2 sposoby:

/* & is explicitly placed in front of .circle */
.demo {
  & .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

lub

/* & + " " space is added for you */
.demo {
  .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

W efekcie wszystkie elementy wewnątrz .demo z klasą .circle są rozmyte i prawie niewidoczne:

W kolorowej siatce kształtów nie ma już okręgów,
    są bardzo niewyraźne w tle.
. Zobacz prezentację
.

Zaznaczanie trójkątów i kwadratów

To zadanie wymaga wybrania wielu zagnieżdżonych elementów, tzw. selektora grupy.

Obecnie bez zagnieżdżania, CSS pozwala na 2 sposoby:

.demo .triangle,
.demo .square {
  opacity: .25;
  filter: blur(25px);
}

lub za pomocą funkcji :is()

/* grouped with :is() */
.demo :is(.triangle, .square) {
  opacity: .25;
  filter: blur(25px);
}

W przypadku zagnieżdżania możesz to zrobić na 2 sposoby:

.demo {
  & .triangle,
  & .square {
    opacity: .25;
    filter: blur(25px);
  }
}

lub

.demo {
  .triangle, .square {
    opacity: .25;
    filter: blur(25px);
  }
}

Wynik – wewnątrz .demo pozostaje tylko tyle elementów: .circle:

Na kolorowej siatki kształtów pozostały tylko okręgi,
    Wszystkie inne kształty są niemal niewidoczne.
. Zobacz prezentację
.

Wybieranie dużych trójkątów i okręgów

To zadanie wymaga selektora złożonego, gdzie Aby elementy zostały wybrane, muszą zawierać obie klasy.

Bez zagnieżdżania obecnie CSS:

.demo .lg.triangle,
.demo .lg.square {
  opacity: .25;
  filter: blur(25px);
}

lub

.demo .lg:is(.triangle, .circle) {
  opacity: .25;
  filter: blur(25px);
}

W przypadku zagnieżdżania możesz to zrobić na 2 sposoby:

.demo {
  .lg.triangle,
  .lg.circle {
    opacity: .25;
    filter: blur(25px);
  }
}

lub

.demo {
  .lg {
    &.triangle,
    &.circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

W efekcie wszystkie duże trójkąty i okręgi są ukryte w obiekcie .demo:

W kolorowej siatce widoczne są tylko małe i średnie kształty.
. Zobacz prezentację
.
Wskazówka dotycząca selektorów złożonych i zagnieżdżania

Symbol & jest Twoim znajomym, ponieważ wskazuje wyraźnie, jak połączyć z zagnieżdżonymi selektory. Na przykład:

.demo {
  .lg {
    .triangle,
    .circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

Chociaż jest to prawidłowy sposób zagnieżdżania, wyniki nie pasują do elementów, których możesz się spodziewać. Powodem jest to, że bez zastosowania funkcji & do określenia pożądanego wyniku połączenia .lg.triangle, .lg.circle rzeczywisty wynik miałby postać .lg .triangle, .lg .circle; selektorów podrzędnych.

Zaznaczam wszystkie kształty z wyjątkiem różowych.

To zadanie wymaga pseudoklasy funkcyjnej negacji, przy czym elementy nie mogą mają określony selektor.

Bez zagnieżdżania obecnie CSS:

.demo :not(.pink) {
  opacity: .25;
  filter: blur(25px);
}

W przypadku zagnieżdżania możesz to zrobić na 2 sposoby:

.demo {
  :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

lub

.demo {
  & :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

W efekcie wszystkie kształty, które nie są różowe, są ukryte w obiekcie .demo:

Kolorowa siatka jest teraz monochromatyczna i zawiera tylko różowe kształty.
. Zobacz prezentację
.
Precyzja i elastyczność dzięki &

Załóżmy, że chcesz kierować reklamy na wybrany kraj lub grupę odbiorców .demo za pomocą selektora :not(). Parametr & jest wymagany w przypadku które:

.demo {
  &:not() {
    ...
  }
}

Powoduje to połączenie danych z .demo i :not() do .demo:not() (w przeciwieństwie do poprzedniego kroku) przykład, który wymaga .demo :not(). To przypomnienie ma bardzo duże znaczenie, z żądaniem zagnieżdżenia interakcji :hover.

.demo {
  &:hover {
    /* .demo:hover */
  }

  :hover {
    /* .demo :hover */
  }
}

Więcej przykładów zagnieżdżania

Specyfikacja CSS na potrzeby zagnieżdżania to mnóstwo przykładów. Jeśli chcesz dowiedzieć się więcej o składni obejmują szeroki zakres prawidłowych i nieprawidłowych przykładów.

W kilku następnych przykładach przedstawimy pokrótce funkcję zagnieżdżania CSS, która pomoże Ci do zrozumienia szerokiego zakresu możliwości, jakie oferuje.

Umieszczanie @media

Przejście do innego obszaru arkusza stylów w celu znalezienia warunki zapytania o media, które modyfikują selektor i jego style. To rozpraszanie uwagi jest wykorzystywana dzięki możliwości zagnieżdżenia warunków bezpośrednio w kontekście.

Dla wygody składni, jeśli zagnieżdżone zapytanie o media modyfikuje tylko style w bieżącym kontekście selektora można użyć minimalnej składni.

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    font-size: 1.25rem;
  }
}

Bezpośrednie użycie atrybutu & można też zastosować:

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    &.large {
      font-size: 1.25rem;
    }
  }
}

W tym przykładzie pokazano rozwiniętą składnię z użyciem słowa &, ale jednocześnie ustawione jest kierowanie na .large. aby zaprezentować dodatkowe funkcje zagnieżdżania.

Dowiedz się więcej o zagnieżdżaniu reguł @rules.

Zagnieżdżanie w dowolnym miejscu

Wszystkie przykłady do tego momentu są kontynuowane lub dołączone w poprzednim kontekście. W razie potrzeby możesz całkowicie zmienić kontekst lub zmienić jego kolejność.

.card {
  .featured & {
    /* .featured .card */
  }
}

Symbol & reprezentuje odwołanie do obiektu selektora (a nie ciągu znaków) oraz można umieścić w dowolnym miejscu selektora zagnieżdżonego. Można go nawet umieścić na kilku stronach, razy:

.card {
  .featured & & & {
    /* .featured .card .card .card */
  }
}

Choć ten przykład wydaje się bezużyteczny, z pewnością istnieją sytuacje, w których możliwość powtarzania kontekstu selektora.

Nieprawidłowe przykłady zagnieżdżania

Istnieje kilka scenariuszy zagnieżdżania, które są nieprawidłowe i mogą zaskoczyć jeśli będzie to proces zagnieżdżenia w obliczeniach wstępnego przetwarzania danych.

Zagnieżdżanie i łączenie

Wiele konwencji nazewnictwa klas CSS liczy na to, że zagnieżdżenie łączy dołącz selektory tak, jakby były to ciągi tekstowe. Nie działa to w przypadku zagnieżdżania CSS, selektory to nie ciągi tekstowe, to odwołania do obiektów.

.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}

Dokładniejsze informacje znajdziesz w specyfikacji.

Przykład nieuczciwego zagnieżdżania

Zagnieżdżanie w listach selektora i polu :is()

Rozważ taki zagnieżdżony blok CSS:

.one, #two {
  .three {
    /* some styles */
  }
}

To pierwszy przykład, który zaczyna się od listy selektorów, a następnie jest nadal zagnieżdżony. Poprzednie przykłady zakończyły się tylko listą selektora. W tym przykładzie zagnieżdżania nie ma nic nieprawidłowego, ale zawiera on potencjalnie trudny szczegół implementacji, jeśli chodzi o zagnieżdżanie list wewnątrz selektorów, zwłaszcza te, które zawierają selektor identyfikatorów.

Aby zagnieżdżenie działało, każda lista selektorów, która nie jest najbardziej zagnieżdżona, zostanie opakowana przez przeglądarkę ciągiem :is(). To opakowanie zachowuje grupowanie listy selektora w dowolnym kontekście tworzenia treści. Efektem ubocznym tej grupy (:is(.one, #two)) jest to, że przyjmuje specyficzność najwyższego wyniku w selektorach w nawiasie. W ten sposób :is() zawsze działa, ale użycie składni zagnieżdżania może powodować niespodziankę, ponieważ nie jest to dokładnie to, co zostało opracowane. Podsumowanie sztuczki: zagnieżdżanie z identyfikatorami i listami selektorów może prowadzić do bardzo szczegółowych selektorów.

Aby wyraźnie podsumować ten trudny przykład, poprzedni blok zagnieżdżenia zostanie zastosowany do dokumentu w ten sposób:

:is(.one, #two) .three {
  /* some styles */
}

Uważaj na zagnieżdżenie w obrębie listy selektora korzystającego z selektora identyfikatora lub naucz je ostrzegać, ponieważ tego typu zagnieżdżenie w obrębie tej listy selektora będzie bardzo dokładne.

Łączenie zagnieżdżania i deklaracji

Rozważ taki zagnieżdżony blok CSS:

.card {
  color: green;
  & { color: blue; }
  color: red;
}

Kolor elementów .card będzie miał wartość blue.

Wszelkie deklaracje stylów wymieszanych są przenoszone na górę, tak jakby były przed zagnieżdżeniem. Więcej informacji znajdziesz w specyfikacji.

Jest kilka sposobów na obejście tego problemu. Poniżej opisujemy 3 style kolorów w tabeli &, które zachowuje porządek kaskadowy zgodnie z zamierzeniami autora. Kolor Elementy .card będą wyświetlane na czerwono.

.card {
  color: green;
  & { color: blue; }
  & { color: red; }
}

Warto też pakować wszystkie style, które są zagnieżdżone, za pomocą atrybutu &.

.card {
  color: green;

  @media (prefers-color-scheme: dark) {
    color: lightgreen;
  }

  & {
    aspect-ratio: 4/3;
  }
}

Wykrywanie cech

Są 2 świetne sposoby wykrywania zagnieżdżenia CSS: użyj zagnieżdżenia @supports, aby sprawdzić możliwość analizowania selektora zagnieżdżenia.

Zrzut ekranu pokazujący wersję demonstracyjną Codepen Bramusa z pytaniem, czy przeglądarka obsługuje
  Zagnieżdżanie CSS. Pod nim znajduje się zielone pole sygnalizujące wsparcie.

Korzystanie z zagnieżdżania:

html {
  .has-nesting {
    display: block;
  }

  .no-nesting {
    display: none;
  }
}

Używasz @supports:

@supports (selector(&)) {
  /* nesting parsing available */
}

Mój współpracownik Bramus ma świetny kod Codepen, który przedstawia tę strategię.

Debugowanie za pomocą Narzędzi deweloperskich w Chrome

Obecnie obsługa zagnieżdżania w Narzędziach deweloperskich jest minimalna. Obecnie można znaleźć style są przedstawiane w panelu Style zgodnie z oczekiwaniami, ale śledzą zagnieżdżenie. i jego pełny kontekst selektora nie jest jeszcze obsługiwany. Mamy projekty i plany, oraz w przejrzysty sposób.

Zrzut ekranu przedstawiający zagnieżdżoną składnię w Narzędziach deweloperskich w Chrome.

W Chrome 113 planujemy wprowadzić dodatkową obsługę zagnieżdżania CSS. Więcej informacji już wkrótce.

Przyszłość

Zagnieżdżanie CSS jest dostępne tylko w wersji 1. W wersji 2 wprowadzimy więcej cukru składowego i mniej reguł zapamiętania. Istnieje duże zapotrzebowanie na nieograniczone możliwości analizy zagnieżdżenia. lub trudnych momentów.

Nesting to duże ulepszenie języka CSS. Wpływa na tworzenie na niemal każdy aspekt architektury CSS. Tak duży wpływ musi być realizowany zdobytą i zrozumiałą, zanim będzie można jednoznacznie określić wersję 2.

Na koniec obejrzyj demonstrację używający łącznie wartości @scope, zagnieżdżenia i @layer. To takie ekscytujące!

Jasna karta na szarym tle. Karta ma tytuł i tekst.
  kilka przycisków polecenia i cyberpunkowy obraz.