Zdefiniowane przez autora nazwy usług CSS i shadow DOM: w specyfikacji i w praktyce

Nazwy CSS zdefiniowane przez autora i DOM cieni mają ze sobą współpracować. Jednak przeglądarki nie są zgodne ze specyfikacją, czasem ze sobą nawzajem, a każda nazwa w CSS jest niespójna w trochę inny sposób.

Z tego artykułu dowiesz się, jak obecnie zachowują się nazwy CSS zdefiniowane przez autora w różnych zakresach cieniowych. Mamy nadzieję, że pomoże Ci to w niedalekiej przyszłości poprawić interoperacyjność.

Czym są nazwy CSS zdefiniowane przez autora?

Nazwy CSS zdefiniowane przez autora to stosunkowo stary mechanizm składni CSS, który został pierwotnie wprowadzony w ramach reguły @keyframes, która definiuje <keyframe-name> jako identyfikator niestandardowy lub ciąg znaków. Celem tego założenia jest zadeklarowanie czegoś w jednej części arkusza stylów i odwoływanie się do niego w innej części.

/* "fade-in" is a CSS name, representing a set of keyframes */
@keyframes fade-in {
  from { opacity: 0 };
  to { opacity: 1 }
}

.card {
  /* "fade-in" is a reference to the above keyframes */
  animation-name: fade-in;
}

Inne funkcje CSS, które używają nazw CSS, to czcionki, deklaracje właściwości, zapytania o kontenery oraz, w ostatnim czasie, animacje sterowane przez przewijanie, pozycjonowanie kotwic i przechodzenie między widokami. W tej niepełnej tabeli znajdują się nazwy, których stan jest sprawdzany przez Chrome.

Funkcja Oświadczenie o nazwie Nazwa
Klatki kluczowe @keyframes animation-name
Czcionki @font-face { }
@font-palette-values
font-family
font-palette
Deklaracje dotyczące usługi @property
Wszelkie niezarejestrowane deklaracje właściwości niestandardowych
var()
Wyświetlanie przejść view-transition-name
view-transition-class
::view-transition-* elementy pseudo
Umieszczenie kotwicy anchor-name position-anchor
Animacja wywoływana przez przewijanie view-timeline-name
scroll-timeline-name
animation-timeline
Style list @counter-style list-style
Liczniki counter-reset
counter-set
counter-increment
Zapytania dotyczące kontenerów container-name @container
Strona page @page

Jak widać w tabeli, nazwa usługi porównywania cen zwykle ma odpowiadającą jej referencję. Na przykład animation-name to odwołanie do nazwy @keyframes. Nazwy CSS różnią się od nazw zdefiniowanych w DOM, takich jak atrybuty i nazwy tagów, ponieważ są deklarowane, a następnie odwołują się do nich w kontekście skryptów.

Jak nazwy są powiązane z shadow DOM

Nazwy CSS służą do tworzenia relacji między różnymi częściami dokumentu lub arkusza stylów, a Shadow DOM działa na odwrót. Zawiera ona relacje, aby nie były one widoczne w komponentach internetowych, które mają mieć własną przestrzeń nazw.

Połączenie nazw CSS i domu kratowego cienia powinno sprawić, że tworzenie komponentów internetowych będzie na tyle elastyczne, aby można było je dowolnie modyfikować, a jednocześnie na tyle ograniczone, aby były stabilne.

To dobrze w teorii. W praktyce przeglądarki nie są spójne w sposobie, w jaki nazwy CSS współdziałają z modelem DOM cieni, zarówno w przypadku funkcji w tej samej przeglądarce, w różnych przeglądarkach, jak i między funkcjami a specyfikacją.

Jak nazwy i DOM cieniowany powinny ze sobą współpracować

Aby zrozumieć problem, warto wiedzieć, jak te części CSS powinny teoretycznie ze sobą współpracować.

Zasada ogólna

Ogólna reguła dotycząca zachowania nazw CSS w drzewach cieni jest zdefiniowana w specyfikacji CSS Scoping Level 1. Podsumowując: nazwa usługi porównywania cen jest globalna w zakresie, w którym jest zdefiniowana, co oznacza, że można uzyskać do niej dostęp z potomnych drzew cieni, ale nie z siostrzanych ani przodkowych drzew cieni. Pamiętaj, że w odróżnieniu od nazw na platformie internetowej, takich jak identyfikatory elementów, które są ujęte w ramach tego samego zakresu drzewa.

Wyjątek od reguły: @property

W przeciwieństwie do innych nazw CSS właściwości CSS nie są opakowane przez DOM cieniowany. Są to raczej wspólne środki przekazywania parametrów między różnymi drzewami cieni. Dzięki temu deskryptor @property jest wyjątkowy: ma działać jak deklaracja typu globalnego dokumentu, która określa działanie określonej nazwanej właściwości. Właściwości muszą być zgodne w drzewach cieni, a niezgodność deklaracji właściwości może powodować nieoczekiwane wyniki. Dlatego deklaracje @property są sformatowane i rozwiązywane zgodnie z kolejnością w dokumencie.

Jak reguła powinna działać w przypadku ::part

Części cienia pozwalają na wyświetlanie elementu w drzewie cienia w drzewie nadrzędnym. Dzięki temu drzewo nadrzędne ma dostęp do tego elementu i może go stylizować za pomocą elementu ::part.

Ponieważ ::part pozwala dwóm zakresom drzewa na nadanie stylu temu samemu elementowi, określono następującą kolejność kaskadową:

  1. Najpierw sprawdź styl w kontekście cienia. Jest to „domyślny” styl części.
  2. Następnie zastosuj styl zewnętrzny zdefiniowany w sekcji ::part. Jest to „spersonalizowany” styl części.
  3. Następnie zastosuj dowolny styl wewnętrzny zdefiniowany razem z elementem !important. Dzięki temu element niestandardowy może zadeklarować, że dana właściwość danego elementu nie może być dostosowywana przez ::part.

Oznacza to, że nazwy w modelu DOM ocienionego nie mogą być używane w elementach ::part, ponieważ ::part jest stylem ograniczonym do hosta, a nie do modelu ocienionego. Na przykład:

// inside the shadow DOM:
@keyframes fade-in {
  from { opacity: 0}
}

// This shouldn't work!
// The host style shouldn't know the name "fade-in"
::part(slider) {
  animation-name: fade-in;  
}

Jak reguła powinna działać w przypadku stylów wbudowanych

W przeciwieństwie do atrybutu ::part atrybuty stylów wbudowanych z atrybutem style lub te, które są ustawiane programowo za pomocą skryptu, są ograniczone do zakresu elementu. Dzieje się tak, ponieważ aby zastosować styl do elementu, musisz mieć dostęp do uchwytu elementu, a tym samym do samego korzenia cienia.

Jak nazwy w CSS i DOM cieni współpracują ze sobą w praktyce

Chociaż powyższe reguły są dobrze zdefiniowane i spójne, ich obecne wdrożenia nie zawsze to odzwierciedlają. W praktyce @property działa w sposób spójny w różnych przeglądarkach, ale większość innych funkcji ma otwarte błędy (niektóre z nich nie zostały jeszcze wydane, więc jest czas na ich naprawę).

Aby przetestować i zademonstrować, jak te funkcje działają w praktyce, utworzyliśmy tę stronę: https://css-names-in-the-shadow.glitch.me/. Ta strona zawiera kilka ramek iframe, z których każda koncentruje się na jednej z funkcji i testuje 6 scenariuszy:

  • Odniesienie zewnętrzne do nazwy zewnętrznej: nie ma potrzeby korzystania z DOM cieniowanego, więc powinno to działać.
  • Odwołania zewnętrzne do nazw wewnętrznych: nie powinny działać, ponieważ oznaczałoby to, że nazwa zdefiniowana w kontekście skrótu została ujawniona.
  • Wewnętrzne odwołanie do nazwy zewnętrznej: powinno to działać, ponieważ nazwy ograniczone do drzewa są dziedziczone przez korzenie cienia.
  • Wewnętrzne odwołanie do wewnętrznej nazwy: powinno to działać, ponieważ nazwa odwołania znajduje się w tym samym zakresie.
  • ::part odwołanie do nazwy zewnętrznej: powinno to działać, ponieważ zarówno ::part, jak i nazwa są zadeklarowane w tym samym zakresie.
  • ::part odwołanie do nazwy wewnętrznej: nie powinno działać, ponieważ zakres zewnętrzny nie może uzyskać informacji o nazwach zadeklarowanych w cieniach DOM.

@keyframes

Zgodnie ze specyfikacją nazwy klatek kluczowych powinny być dostępne w rdzeniu schatten, o ile reguła at-rule @keyframes znajduje się w zakresie przodka. W praktyce żaden przeglądarka nie wdraża tego zachowania, a definicje klatek kluczowych mogą być używane tylko w zakresie, w którym zostały zdefiniowane. Zobacz problem 10540.

@property

Zgodnie ze specyfikacją wszystkie deklaracje @property zostaną spłaszczone do zakresu dokumentu. Obecnie we wszystkich przeglądarkach można deklarować tylko atrybuty @property w zakresie dokumentu, a deklaracje atrybutów @property w korzeniach cienia są ignorowane.
Zobacz problem 10541.

Błędy związane z przeglądarką

Pozostałe funkcje nie działają w taki sam sposób w różnych przeglądarkach:

  • @font-face jest spłaszczone do zakresu katalogu źródeł w Safari.
  • Chromium nie zezwala na dziedziczenie reguł anchor-name w katalogu cieni.
  • scroll-timeline-nameview-timeline-name nie są prawidłowo ograniczone do ::part (także w Chromium).
  • Żadna przeglądarka nie zezwala na deklarowanie @font-palette-values w katalogu głównym cienia.
  • view-transition-class można zdefiniować w korzeniach zduplikowanych (sama przejście znajduje się poza korzeniami zduplikowanymi).
  • Firefox umożliwia ::part dostęp do nazw cieni wewnętrznych (zapytania dotyczące kontenera, klatki kluczowe).
  • Firefox i Safari nie uwzględniają @counter-style w katalogu cieni.

Pamiętaj, że counter-reset, counter-setcounter-increment mają nieco inne reguły, ponieważ są to nazwy domyślne, a deklarowanie właściwości CSS podlega ustalonemu i dobrze przetestowanemu zestawowi reguł.

Podsumowanie

Złe wieści są takie, że przy obecnym stanie interoperacyjności w przypadku nazw CSS i domu kratowego cienia występują niespójności i błędy. Żadna z badanych przez nas funkcji nie działa w sposób spójny w różnych przeglądarkach i zgodnie ze specyfikacją. Dobra wiadomość jest taka, że różnica, która powoduje niespójności, to ograniczona lista błędów i problemów ze specyfikacją. Naprawmy to. Mamy nadzieję, że ten artykuł pomoże Ci rozwiązać problemy z niespójnościami opisanymi w tym artykule.