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, co jest nowością, animacje sterowane przewijaniem, 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
Dowolna deklaracja niezarejestrowanej właściwości niestandardowej
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 kontenera container-name @container
Strona page @page

Jak widać w tabeli, nazwa usługi porównywania cen zwykle odpowiada jej odwołaniu. 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 zapewnić elastyczność, ale też na tyle ograniczone, aby zapewnić stabilność.

Teoretycznie jest to dobre. W praktyce przeglądarki nie są spójne pod względem sposobu, w jaki nazwy CSS współdziałają z modelem shadow DOM, 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 model shadow DOM powinny 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 CSS jest globalna w zakresie, w którym jest zdefiniowana. Oznacza to, że można uzyskać do niej dostęp z drzew potomnych cieni, ale nie z drzew potomnych lub nadrzędnych. Pamiętaj, że w odróżnieniu od nazw na platformie internetowej, takich jak identyfikatory elementów, które są zapieczętowane w tym samym zakresie drzewa.

Wyjątek od reguły: @property

W przeciwieństwie do innych nazw CSS właściwości CSS nie są otoczone przez DOM cieniowany. Są to raczej wspólne środki przekazywania parametrów między różnymi drzewami cieni. To sprawia, że deskryptor @property jest wyjątkowy: ma on 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 powodowałaby nieoczekiwane wyniki. Dlatego deklaracje @property są sformatowane i rozwiązywane zgodnie z kolejnością w dokumencie.

Jak reguła powinna działać w przypadku funkcji ::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 zgodnie z definicją 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 nie można odwoływać się do nazw z modelu shadow DOM za pomocą interfejsu ::part, ponieważ ::part to styl ograniczony do hosta, a nie ograniczony do cienia. 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 odróżnieniu od ::part style wbudowane z atrybutem style lub te, które automatycznie ustawiają styl za pomocą skryptu, mają zakres ograniczony do zakresu elementu. Wynika to z faktu, że zastosowanie stylu do elementu wymaga dostępu do uchwytu elementu, a tym samym do samego poziomu głównego.

Jak nazwy CSS i shadow DOM współdziałają w rzeczywistości

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ć działanie tych funkcji w praktyce, utworzyliśmy 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 jest wymagane shadow DOM, więc powinno 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 odniesienie do nazwy zewnętrznej: powinno to zadziałać, ponieważ nazwy ograniczone do drzewa są dziedziczone przez rdzenie podrzędne.
  • Wewnętrzne odwołanie do wewnętrznej nazwy: powinno to działać, ponieważ nazwa odwołania znajduje się w tym samym zakresie.
  • Odwołanie ::part do nazwy zewnętrznej: powinno to zadział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 z definicją w specyfikacji każda deklaracja wartości @property zostanie spłaszczona 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.
Przeczytaj 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 głównym
  • Atrybuty scroll-timeline-name i view-timeline-name mają nieprawidłowy zakres w witrynie ::part (również w Chromium).
  • Żadna przeglądarka nie zezwala na zadeklarowanie wartości @font-palette-values w rdzeniach cieni.
  • view-transition-class można zdefiniować w korzeniach zduplikowanych (sama zmiana jest 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ą problemy z niespójnością i błędami. Żadna z badanych przez nas funkcji nie działa w spójny sposób we wszystkich 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.