Nomi CSS definiti dall'autore e shadow DOM: nella specifica e nella pratica

I nomi CSS definiti dallo scrittore e lo shadow DOM dovrebbero funzionare insieme. Tuttavia, i browser non sono coerenti con le specifiche, a volte con e ogni nome CSS risulta incoerente in modo leggermente diverso.

Questo articolo documenta lo stato attuale del comportamento dei nomi CSS definiti dall'autore attraverso gli ambiti shadow, nella speranza che possano fungere da guida per migliorare per l'interoperabilità nel prossimo futuro.

Cosa sono i nomi CSS definiti dall'autore?

I nomi CSS definiti dall'autore sono un meccanismo di sintassi CSS relativamente vecchio, originariamente introdotto per la regola @keyframes, che definisce un <keyframe-name> come un custom-ident o una stringa. Lo scopo di questo concetto è dichiarare qualcosa in una parte di un foglio di stile e farvi riferimento in un'altra.

/* "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;
}

Altre funzionalità CSS che utilizzano i nomi CSS sono caratteri, dichiarazioni delle proprietà, query container e, più di recente, hanno visto transizioni, posizionamento animazioni basate sullo scorrimento. La seguente tabella non completa include i nomi di cui Chrome controlla lo stato.

Funzionalità Dichiarazione relativa al nome Riferimento nome
Fotogrammi chiave @keyframes animation-name
Caratteri @font-face { }
@font-palette-values
font-family
font-palette
Dichiarazioni di proprietà @property Qualsiasi proprietà personalizzata
Visualizza transizione view-transition-name
view-transition-class
::view-transition-group()
Posizionamento degli ancoraggi anchor-name position-anchor
Animazione con scorrimento animation-timeline view-timeline-name
scroll-timeline-name
Stile contatore @counter-style
Counter-reset
counter-set
counter-increment
list-style
Query container container-name @container
Variabile CSS --something var(--something)
Pagina @page

Come puoi vedere nella tabella, un nome CSS di solito è associato a un riferimento. Ad esempio, animation-name è un riferimento a @keyframes . I nomi CSS sono diversi dai nomi definiti nel DOM, come gli attributi e i nomi dei tag, poiché vengono dichiarati e vi viene fatto riferimento nel contesto e i fogli di stile.

Correlazione dei nomi allo shadow DOM

Sebbene i nomi CSS siano creati per creare relazioni tra le diverse parti di un documento o foglio di stile, Shadow DOM è progettato per fare il contrario. Incapsula le relazioni in modo che non si diffondano tra componenti web che dovrebbero avere un proprio spazio dei nomi.

Combinando i nomi CSS e lo shadow DOM, l'esperienza di composizione i componenti web devono essere abbastanza espressivi da essere flessibili, ma vincolati abbastanza per essere stabili.

Questo va bene in teoria. In pratica, i browser non sono coerenti con il modo in cui CSS interagiscono con lo shadow DOM, entrambi tra le caratteristiche nello stesso browser, su tutti i browser, e tra le funzionalità e le specifiche.

Modalità di interazione tra nomi e shadow DOM

Per comprendere il problema, vale la pena comprendere in che modo queste parti del CSS dovrebbero funzionare insieme in teoria.

La regola generale

La regola generale per il comportamento dei nomi CSS negli alberi ombre è definita nel Specifica del livello 1 dell'ambito dei CSS. Riassumendo: un nome CSS è globale nell'ambito in cui è definito, ovvero è accessibile dagli alberi ombre discendenti, ma non da quelli di pari livello ombre dei predecessori. Tieni presente che sono diversi dai nomi nella piattaforma web, ad esempio: ID elemento, che sono incapsulati nello stesso ambito ad albero.

Eccezione alla regola: @property

A differenza degli altri nomi CSS, le proprietà CSS non sono incapsulate dallo shadow DOM. Piuttosto, sono il mezzo comune per trasferire parametri tra diverse ombre alberi. Ciò rende Descrittore @property speciale: dovrebbe comportarsi come una dichiarazione di tipo documento-globale che definisce il comportamento di una determinata proprietà con nome. Poiché le proprietà devono corrispondere tra gli alberi ombra, la mancata corrispondenza delle dichiarazioni relative alla proprietà creerebbe risultati, pertanto le dichiarazioni @property devono essere suddivise e risolte secondo l'ordine dei documenti.

Come dovrebbe funzionare la regola con ::part

Parti ombra esporre un elemento all'interno di un albero ombra al relativo albero principale. In questo modo, La struttura principale può accedere all'elemento e anche applicargli uno stile mediante l'::part .

Poiché ::part consente a due ambiti ad albero di applicare uno stile allo stesso elemento, quanto segue l'ordine a cascata è specificato:

  1. Innanzitutto, controlla lo stile nel contesto delle ombre. Questo è il valore "predefinito" lo stile della parte.
  2. poi applica lo stile esterno come definito in ::part. Questo è il "personalizzato" lo stile della parte.
  3. poi applica uno stile interno definito insieme a !important. Ciò consente a un elemento personalizzato di dichiarare che una determinata proprietà di un non è personalizzabile da ::part.

Ciò significa che non è possibile fare riferimento ai nomi all'interno del DOM shadow da un ::part, poiché ::part è uno stile con ambito host e non con ambito shadow lo stile del testo. Ad esempio:

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

Come dovrebbe funzionare la regola con gli stili incorporati

A differenza di ::part, gli stili incorporati con l'attributo style o quelli l'impostazione programmatica dello stile tramite lo script restringe l'ambito al punto in cui l'elemento a cui è limitato l'ambito. Il motivo è che per applicare uno stile a un elemento a cui devi accedere all'handle dell'elemento e, di conseguenza, alla radice ombra stessa.

Come i nomi CSS e lo shadow DOM funzionano insieme nella realtà

Sebbene le regole precedenti siano ben definite e coerenti, non sempre le implementazioni riflettono questa caratteristica. In pratica, @property funziona in modo coerente rispetto alle specifiche nei vari browser e la maggior parte delle altre funzioni presenta bug aperti (alcune sono non ancora rilasciate, quindi c'è tempo per correggerle).

Per testare e dimostrare il funzionamento pratico di queste funzionalità, abbiamo creato pagina seguente: https://css-names-in-the-shadow.glitch.me/. Questa pagina contiene diversi iframe, ognuno incentrato su una delle funzionalità e sei scenari aggiuntivi:

  • Riferimento esterno a un nome esterno: non è coinvolto lo shadow DOM, che dovrebbe al lavoro.
  • Riferimento esterno a un nome interno: non dovrebbe funzionare, in quanto significa che il nome definito nel contesto ombra è trapelato.
  • Riferimento interno al nome esterno: dovrebbe funzionare, in quanto nomi con ambito ad albero. sono ereditati dalle radici shadow.
  • Riferimento interno al nome interno: dovrebbe funzionare, in quanto sia il nome del nome riferimento rientrano nello stesso ambito.
  • Riferimento ::part al nome esterno: dovrebbe funzionare, in quanto ::part e nomi siano dichiarati nello stesso ambito.
  • Riferimento ::part al nome interno: non dovrebbe funzionare, in quanto ambito esterno non dovrebbero essere a conoscenza dei nomi dichiarati all'interno dello shadow DOM.

@keyframes

Come definito nella specifica, dovresti essere in grado di fare riferimento ai nomi dei fotogrammi chiave dall'interno di una radice ombra, purché la regola at @keyframes sia in un predecessore l'ambito di attività. In pratica, nessun browser implementa questo comportamento e il fotogramma chiave è possibile fare riferimento alle definizioni solo nell'ambito in cui sono definite. Consulta problema 10540.

@property

Come definito nella specifica, qualsiasi dichiarazione di @property sarà ridimensionato all'ambito del documento. Oggi, tuttavia, in tutti i browser è possibile dichiarare @property nell'ambito del documento e nelle dichiarazioni @property entro le radici shadow vengono ignorate.
Vedi il problema 10541.

Bug specifici del browser

Le altre funzionalità non mostrano un comportamento coerente tra i vari browser:

  • @font-face è allineato all'ambito principale in Safari.
  • Chromium non consente di ereditare regole @anchor-name in una radice shadow
  • L'ambito di @scroll-timeline-name e @view-timeline-name non è corretto su ::part (anche in Chromium).
  • Nessun browser consente di dichiarare @font-palette-values in una radice shadow.
  • view-transition-class può essere definito all'interno di una radice ombra (la transizione è al di fuori della radice ombra).
  • Firefox consente a ::part di accedere ai nomi shadow interni (query container, fotogrammi chiave).
  • Firefox e Safari non rispettano @counter-style in una radice shadow.

Tieni presente che counter-reset, counter-set e counter-increment sono leggermente interessati regole diverse perché sono nomi impliciti e che dichiarano proprietà CSS un insieme di regole consolidate e collaudate.

Conclusione

La cattiva notizia è che quando si esamina l'istantanea dello stato di interoperabilità attuale per quanto riguarda i nomi CSS e lo shadow DOM, l'esperienza non è coerente con problemi. Nessuna delle funzionalità che abbiamo esaminato si comporta in modo coerente browser e in base alle specifiche. La buona notizia è che il delta per rendere l'esperienza coerente è limitato di bug e problemi con le specifiche. Risolviamo il problema. Nel frattempo, questa panoramica può esserti utile in caso di problemi con il incoerenze descritte in questo articolo.