Noms CSS définis par l'auteur et Shadow DOM: dans les spécifications et dans la pratique

Les noms CSS définis par les auteurs et le Shadow DOM sont censés fonctionner ensemble. Cependant, les navigateurs ne sont pas cohérents avec la spécification, parfois avec chaque et les noms de CSS présentent des incohérences légèrement différentes.

Cet article décrit l'état actuel du comportement des noms CSS définis par l'auteur. dans les champs d'application de l'ombre, en espérant qu'ils puissent servir de guide pour améliorer leur interopérabilité.

Que sont les noms CSS définis par l'auteur ?

Les noms CSS définis par l'auteur sont un mécanisme de syntaxe CSS relativement ancien, introduit pour la règle @keyframes, qui définit un <keyframe-name> comme soit un identifiant personnalisé, soit une chaîne. Ce concept vise à déclarer d'un élément dans une partie d'une feuille de style et faire référence à celui-ci dans une autre partie.

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

Les polices, les déclarations de propriété sont d'autres fonctionnalités CSS des requêtes de conteneur et, plus récemment, les transitions de vues, le positionnement des ancres et des animations liées au défilement. Le tableau non complet suivant inclut les noms dont Chrome vérifie l'état.

Fonctionnalité Déclaration du nom Référence de nom
Images clés @keyframes animation-name
Polices @font-face { }
@font-palette-values
font-family
font-palette
Déclarations de propriété @property N'importe quelle propriété personnalisée
Afficher la transition view-transition-name
view-transition-class
::view-transition-group()
Positionnement de l'ancre anchor-name position-anchor
Animation liée au défilement animation-timeline view-timeline-name
scroll-timeline-name
Style de compteur @counter-style
Counter-reset
counter-set
counter-increment
list-style
Requêtes de conteneur container-name @container
Variable CSS --something var(--something)
Page @page

Comme vous pouvez le voir dans le tableau, un name CSS possède généralement un CSS référence. Par exemple, animation-name est une référence au @keyframes. son nom. Les noms CSS sont différents de ceux définis dans le DOM, comme les attributs. et les noms de tags, car ils sont déclarés puis référencés dans le contexte feuilles de style.

Lien entre les noms et le Shadow DOM

Alors que les noms CSS sont conçus pour créer des relations entre différentes parties d'une ou d'une feuille de style, le Shadow DOM est construit pour faire le contraire. Il encapsule les relations pour éviter les fuites sur des composants Web censés avoir leur propre espace de noms.

En associant les noms CSS et le Shadow DOM, vous pouvez Les composants Web doivent être suffisamment expressifs pour être flexibles, mais limités. pour être stables.

C'est une bonne théorie. En pratique, les navigateurs n'ont pas le même style CSS interagissent avec le Shadow DOM, les deux fonctionnalités au sein d'une même pour tous les navigateurs, et entre les fonctionnalités et la spécification.

Fonctionnement des noms et du Shadow DOM

Pour comprendre le problème, il est utile de comprendre comment devraient fonctionner ensemble en théorie.

Règle générale

La règle générale régissant le comportement des noms CSS dans les arbres d'ombre est définie dans Spécification du niveau 1 de champ d'application CSS. Pour résumer, un nom CSS est global dans le champ d'application dans lequel il est défini. Autrement dit, il est accessible depuis les arbres descendants, mais pas depuis les frères ou sœurs ou les arbres fantômes ancêtres. Notez que cela diffère des noms utilisés sur la plate-forme Web comme des ID d'éléments, qui sont encapsulés dans le même champ d'application d'arborescence.

Exception à la règle: @property

Contrairement aux autres noms CSS, les propriétés CSS ne sont pas encapsulées par le Shadow DOM. Il s'agit plutôt du moyen le plus courant de transmettre des paramètres à différentes zones d'ombre arbres. Ainsi, Descripteur @property spécial: il est censé se comporter comme une déclaration de type document-global qui définit le comportement d'une propriété nommée spécifique. Parce que les établissements doivent correspondre entre les arbres fantômes, une non-concordance des déclarations de propriété résultats. Les déclarations @property sont donc spécifiées comme étant aplaties et résolues. conformément à l'ordre des documents.

Fonctionnement de la règle avec ::part

Ombres expose un élément situé à l'intérieur d'une arborescence fantôme à son arborescence parente. Ainsi, l'arborescence parente peut accéder à cet élément et lui appliquer un style à l'aide de ::part .

Étant donné que ::part permet à deux champs d'application d'arborescence de styliser le même élément, les éléments suivants l'ordre en cascade est spécifié:

  1. Tout d'abord, vérifiez le style dans le contexte de l'ombre. Il s'agit de l'option "par défaut" et le style de la pièce.
  2. Appliquez ensuite le style externe tel que défini dans ::part. Il s'agit de la "personnalisé" et le style de la pièce.
  3. Appliquez ensuite tout style interne défini avec !important. Cela permet à un élément personnalisé de déclarer qu'une certaine propriété d'une certaine La partie n'est pas personnalisable par ::part.

Cela signifie que les noms issus du Shadow DOM ne peuvent pas être référencés à partir d'un ::part, car ::part est un style de portée hôte plutôt que de portée ombre. du style. Exemple :

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

Fonctionnement de la règle avec les styles intégrés

Contrairement à ::part, les styles intégrés avec l'attribut style ou ceux en définissant le style par programmation à l'aide d'un script, sont limités à l'endroit où l'élément est limité. En effet, pour appliquer un style à un élément auquel vous avez besoin d'accéder la poignée de l’élément, et donc à la racine de l’ombre elle-même.

Comment les noms CSS et le Shadow DOM fonctionnent ensemble en réalité

Bien que les règles précédentes soient bien définies et cohérentes, les implémentations ne reflètent pas toujours cela. En pratique, @property fonctionne différemment des spécifications de la spécification de manière cohérente. entre les navigateurs, et la plupart des autres fonctionnalités présentent des bugs ouverts (certains sont des pas encore sortis, il est donc temps de les corriger).

Pour tester et démontrer le fonctionnement de ces fonctionnalités en pratique, nous avons créé page suivante: https://css-names-in-the-shadow.glitch.me/. Cette page comporte plusieurs cadres iFrame, chacun étant axé sur l'une de ses fonctionnalités et teste six scénarios:

  • Référence externe à un nom externe: aucun Shadow DOM n'est utilisé, ce qui doit travail.
  • Référence extérieure à un nom interne: ceci ne devrait pas fonctionner, signifie que le nom défini dans le contexte "Shadow" a été divulgué.
  • Référence interne au nom externe: ceci doit fonctionner, car il s'agit de noms arborescence. sont héritées par les racines fantômes.
  • Référence interne au nom interne: ceci doit fonctionner, car à la fois le nom du ont le même champ d'application.
  • Référence ::part au nom externe: cela doit fonctionner, car ::part est à la fois et le nom sont déclarés dans le même champ d'application.
  • Référence ::part au nom interne: cela ne devrait pas fonctionner, car le champ d'application externe ne devrait pas connaître les noms déclarés dans le Shadow DOM.

@keyframes

Comme défini dans la spécification, vous devez pouvoir référencer des noms d'images clés depuis une racine fantôme, à condition que la règle @keyframes at-rule se trouve dans un ancêtre le champ d'application. En pratique, aucun navigateur ne met en œuvre ce comportement, et l'image clé les définitions ne peuvent être référencées que dans le champ d'application dans lequel elles sont définies. Voir problème 10540.

@property

Comme défini dans la spécification, toute déclaration de @property sera aplatie dans la portée du document. Mais aujourd'hui, dans tous les navigateurs, vous ne pouvez déclarer @property dans le champ d'application du document et @property dans le champ d'application les racines fantômes sont ignorées.
Consultez le problème 10541.

Bugs spécifiques au navigateur

Les autres fonctionnalités n'offrent pas un comportement cohérent d'un navigateur à l'autre:

  • @font-face est aplati au niveau du champ d'application racine dans Safari.
  • Chromium n'autorise pas l'héritage de règles @anchor-name dans une racine fantôme
  • Le champ d'application de @scroll-timeline-name et @view-timeline-name n'est pas correct sur ::part (également dans Chromium).
  • Aucun navigateur ne permet de déclarer @font-palette-values dans une racine fantôme.
  • view-transition-class peut être défini à l'intérieur d'une racine fantôme (la transition se trouve en dehors de la racine de l'ombre).
  • Firefox permet à ::part d'accéder aux noms fantômes internes (requêtes de conteneur, images clés).
  • Firefox et Safari ne respectent pas @counter-style dans une racine fantôme.

Notez que counter-reset, counter-set et counter-increment ont légèrement des règles différentes, car il s'agit de noms implicites qui déclarent des propriétés CSS. disposent d'un ensemble de règles établi et testé.

Conclusion

Mauvaise nouvelle : si vous examinez l'instantané de l'état d'interopérabilité actuel, En ce qui concerne les noms CSS et le Shadow DOM, l'expérience est incohérente et avec des bugs. Aucune des fonctionnalités que nous avons examinées ici ne se comporte de manière cohérente et selon les spécifications. La bonne nouvelle, c'est que le delta pour rendre l'expérience cohérente est une liste de bugs et de problèmes de spécifications. Résolvons à présent ce problème. En attendant, nous espérons que cette présentation vous sera utile si vous rencontrez des difficultés les incohérences décrites dans cet article.