Warstwy kaskadowe wkrótce będą dostępne w Twojej przeglądarce

Warstwy kaskadowe (@layerreguła CSS) pojawią się w Chromium 99, Firefox 97 i Safari 15.4 Beta. Umożliwiają one bardziej szczegółową kontrolę nad plikami CSS, aby zapobiegać konfliktom związanym ze stylami. Jest to szczególnie przydatne w przypadku dużych baz kodu, systemów projektowania i zarządzania stylami innych firm w aplikacjach.

Umieszczanie warstw CSS w przejrzysty sposób zapobiega nieoczekiwanym zastąpieniom stylów i poprawia architekturę CSS.

Specyficzność CSS i kaskada

Specyficzność CSS określa, które style mają być stosowane do których elementów. Różne selektory, których możesz używać, określają specyfikę reguły stylu. Na przykład elementy są mniej szczegółowe niż klasy czy atrybuty, które z kolei są mniej szczegółowe niż identyfikatory. Jest to podstawowa część nauki CSS.

Aby zapobiec przypadkowemu zastąpieniu specyficzności, ludzie stosują konwencje nazewnictwa CSS, takie jak BEM. Nadawanie wszystkim obiektom tej samej nazwy klasy powoduje, że wszystkie obiekty są umieszczane na tym samym poziomie szczegółowości. Nie zawsze jednak można zachować taką organizację stylów, zwłaszcza podczas pracy z kodem i systemami projektowania innych firm.

Wizualizacja BEM karty z zajęciami
Ilustrowany przykład nazewnictwa BEM z keepinguptodate.com

Warstwy kaskadowe mają na celu rozwiązanie tego problemu. Wprowadzają nową warstwę do kaskady CSS. W przypadku stylów warstwowych pierwszeństwo warstwy zawsze wygrywa ze specyficznością selektora.

Na przykład selektor .post a.link ma większą specyficzność niż .card a. Jeśli spróbujesz nadać styl linkowi na karcie w poście, zostanie zastosowany bardziej szczegółowy selektor.

Dzięki użyciu @layer możesz bardziej precyzyjnie określić specyficzność stylu każdego z nich i upewnić się, że style linku do karty zastąpią style linku do posta, nawet jeśli specyficzność może być liczbowo niższa, jeśli cała usługa porównywania cen znajduje się na tym samym poziomie. Wynika to z hierarchii ustawień. Stylizowane warstwy tworzą nowe kaskadowe „płaszczyzny”.

Ilustracja z demonstracji projektu dotyczącej wyodrębniania interfejsu

@layer w działaniu

Demonstracja pokazująca kolory linków w przypadku importów
Zobacz prezentację na Codepen

Ten przykład pokazuje możliwości warstw kaskadowych na przykładzie @layer. Wyświetla się kilka linków: niektóre bez żadnych dodatkowych nazw klas, jeden z klasą .link i jeden z klasą .pink. Kod CSS dodaje następnie 3 warstwy: base, typography i utilities, jak pokazano poniżej:

@layer base {
  a {
    font-weight: 800;
    color: red; /* ignored */
  }

  .link {
    color: blue; /* ignored */
  }
}

@layer typography {
  a {
    color: green; /* styles *all* links */
  }
}

@layer utilities {
  .pink {
    color: hotpink;  /* styles *all* .pink's */
  }
}

Ostatecznie wszystkie linki są zielone lub różowe. Dzieje się tak, ponieważ .link ma wyższą specyficzność na poziomie selektora niż a, ale styl kolorów a ma wyższą ważność niż @layer. a { color: green } zastępuje .link { color: blue }, gdy reguła zielona znajduje się w warstwie po regule niebieskiej.

Pierwszeństwo warstwy ma większą wagę niż szczegółowość elementu.

porządkowanie warstw,

Warstwy możesz porządkować bezpośrednio na stronie, jak pokazano powyżej, lub u góry pliku.

Kolejność warstw jest ustalana na podstawie tego, kiedy po raz pierwszy pojawia się w kodzie nazwa każdej warstwy.

Oznacza to, że jeśli dodasz do góry pliku ten fragment kodu, wszystkie linki będą czerwone, a link z klasą .link będzie niebieski:

@layer utilities, typography, base;

Dzieje się tak, ponieważ kolejność warstw została odwrócona, a na początku znajdują się teraz narzędzia, a na końcu podstawa. Dlatego reguły stylu w warstwie base będą zawsze miały większą specyficzność niż reguły stylu w warstwie typografii. Linki nie będą już zielone, tylko czerwone lub niebieskie.

Zrzut ekranu projektu Codepen
Zobacz prezentację na Codepen

porządkowanie importów,

Innym sposobem korzystania z @layer jest importowanie plików. Możesz to zrobić bezpośrednio podczas importowania stylów, używając funkcji layer(), jak w tym przykładzie:

/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */

/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */

/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */

Powyższy fragment kodu zawiera 3 poziomy: base, layoutscomponents. Pliki normalizacji, motywy i typografii w folderze base, plik post w folderze layouts oraz pliki cardsfooter w folderze components. Podczas importowania pliku warstwy są tworzone za pomocą funkcji warstwy. Inną metodą jest uporządkowanie warstw u góry pliku i ogłoszenie ich przed importem:

@layer base,
       theme,
       layouts,
       components,
       utilities;

Kolejność, w jakiej @import stylów nie ma znaczenia dla kolejności warstw, ponieważ jest ona już ustalona w przypadku pierwszego wystąpienia nazwy warstwy. O jedno zmartwienie mniej. Nadal możesz przypisać zaimportowane pliki do określonych warstw, ale kolejność jest już ustalona.

Zrzut ekranu z projektu Codepen
Zobacz ten projekt na Codepen

Warstwy i kaskada

Wróćmy do ogólnego opisu i zobaczmy, gdzie są używane warstwy w ramach szerszej kaskady:

Ilustracja z Cascade

Kolejność obowiązywania zasad:

  • Klient użytkownika (normalny – najniższy priorytet)
  • Użytkownik lokalny @layer
  • Użytkownik lokalny normalny
  • Autor @layers
  • Autor normalny
  • Autor !important
  • Autor @layer !important
  • Użytkownik lokalny !important
  • Klient użytkownika !important** (najwyższy priorytet)

Zauważysz, że style @layer !important są odwrócone. Zamiast być mniej szczegółowe niż style bez warstw (normalne), mają wyższy priorytet. Wynika to z działania funkcji !important w kaskadzie: przerywa ona normalną kaskadę w swój stylach i odwraca normalną specyficzność na poziomie warstwy (pierwszeństwo).

Zagnieżdżone warstwy

Warstwy mogą być też zagnieżdżone w inne warstwy. Ten przykład pochodzi z treści Miriam Suzanne na temat warstw kaskadowych:

@layer default {
  p { max-width: 70ch; }
}

@layer framework {
  @layer default {
    p { margin-block: 0.75em; }
  }

  p { margin-bottom: 1em; }
}

W powyższym fragmencie kodu możesz uzyskać dostęp do framework.default, używając . jako wskaźnika warstwy default zagnieżdżonej w poziomie framework. Możesz też użyć skrótu:

@layer framework.default {
  p { margin-block: 0.75em }
}

Powstałe warstwy i ich kolejność:

  • domyślna
  • framework.default
  • framework bez warstw
  • bez warstw

Na co zwrócić uwagę

Warstwy kaskadowe mogą być przydatne, jeśli używasz ich prawidłowo, ale mogą też powodować dodatkowe zamieszanie i nieoczekiwane wyniki. Podczas pracy z warstwami kaskadowymi należy zwrócić uwagę na te kwestie:

Zasada 1. Nie używaj elementu @layer do określania zakresu

Warstwy kaskadowe nie rozwiązują problemu z określaniem zakresu. Jeśli masz plik CSS z elementem @layer, np. card.css, i chcesz nadać styl wszystkim linkom w karcie, nie pisz stylów w ten sposób:

a {
  
}

Spowoduje to zastąpienie wszystkich tagów a w pliku. Nadal ważne jest prawidłowe określanie zakresu stylów:

.card a {
  
}

Reguła 2. Warstwy kaskadowe są uporządkowane za CSS bez warstw

Pamiętaj, że plik CSS z warstwami nie zastąpi kod CSS bez warstw. Ta decyzja była zamierzona, ponieważ ułatwia wprowadzenie warstw w bardziej sensowny sposób, aby można było pracować z dotychczasową bazą kodu. Używanie pliku reset.css to dobry punkt wyjścia i przypadek użycia warstw kaskadowych.

Reguła 3. !important odwraca specyficzność kaskadową

Chociaż style warstwowe są ogólnie mniej szczegółowe niż style bez warstw, użycie !important odwraca tę zależność. W warstwie deklaracje z regułą !importantbardziej szczegółowe niż style bez warstw.

W takim przypadku style !important odwracają swoją specyficzność. Poniższy diagram pokazuje to na potrzeby odniesienia: autor @warstwy ma mniejszy priorytet niż autor normalny, który ma mniejszy priorytet niż autor !important, który ma mniejszy priorytet niż autor @warstwa !important.

Jeśli masz kilka warstw, pierwsza warstwa z !important będzie miała pierwszeństwo przed !important i będzie najbardziej szczegółowym stylem.

Reguła 4. Punkty wstrzyknięcia

Kolejność warstw jest ustalana na podstawie tego, kiedy po raz pierwszy pojawia się w kodzie nazwa każdej warstwy. Jeśli więc umieścisz deklarację @layer po zaimportowaniu i ustawieniu layer() lub po innym oświadczeniu @layer, może ona zostać zignorowana. W przeciwieństwie do CSS, gdzie reguła stylu znajdująca się najdalej na dole strony jest stosowana do warstw kaskadowych, kolejność jest ustalana w pierwszej instancji.

Możesz użyć listy, bloku warstwy lub importu. Jeśli umieścisz @layer po liście importu z layer(), nic się nie stanie. Umieszczenie go na szczycie pliku spowoduje ustawienie kolejności warstw i ułatwi wyraźne widzenie warstw w architekturze.

Reguła 5. Uważaj na specyfikę

W przypadku warstw kaskadowych mniej szczegółowy selektor (np. a) zastąpi bardziej szczegółowy selektor (np. .link), jeśli ten mniej szczegółowy selektor znajduje się na bardziej szczegółowej warstwie. Weź pod uwagę następujące kwestie:

Wartość a w elementach layer(components) zastąpi wartość .pink w elementach layer(utilities), jeśli określono wartość @layer utilities, components. Jest to celowa część interfejsu API, ale może być myląca i frustrująca, jeśli nie spodziewasz się takiej sytuacji.

Jeśli więc piszesz klasy pomocnicze, zawsze uwzględniaj je jako warstwę wyższego rzędu niż komponenty, które zamierzasz zastąpić. Możesz pomyśleć: „Dodałem właśnie klasę .pink, aby zmienić kolor, ale nie działa”.

Więcej informacji o warstwach kaskadowych

Aby dowiedzieć się więcej o warstwach kaskadowych, zapoznaj się też z tymi materiałami: