web-dev-qa-db-fra.com

Qu'est-ce que le pseudo-élément :: content / :: slotted et comment fonctionne-t-il?

Cela est impossible pour Google, car chaque article parlant du :before et :after les pseudo-éléments semblent utiliser le mot "contenu".

J'en ai entendu parler dans this CSS-Tricks article, expliquant comment implémenter un curseur d'image comme exemple d'utilisation pour les composants Web. L'exemple de code dans lequel il apparaît est donc:

[~ # ~] css [~ # ~]

#slides ::content img {
   width: 25%;
   float: left;
}

[~ # ~] html [~ # ~]

<template>
  ...
  <div class="inner">
    <content select="img"></content>
  </div>
</template>

Il semble faire référence à ce <content> tag, qui est utilisé pour permettre à l'utilisateur d'inclure des composants Web, mais j'aimerais mieux comprendre cela.

MODIFIER:

Après avoir lu plus loin, dans l'article susmentionné, j'ai découvert un lien vers le "Shadow DOM CSS Cheatsheet" de l'auteur qui comprend un passage qui explique ce que le ::content le pseudo-élément est:

Sélectionne des nœuds distribués à l'intérieur d'un élément. Doit être associé à polyfill-next-selector pour les navigateurs qui ne prennent pas en charge le sélecteur natif.

::content h1 {
    color: red;
}

Source: http://robdodson.me/blog/2014/04/10/shadow-dom-css-cheat-sheet/

C'est utile, mais je trouve quand même toute l'affaire plutôt opaque. Des informations supplémentaires?

73
jon

Le ::content le pseudo-élément sera remplacé dans les futures implémentations de Web Components/Shadow DOM par le ::slotted pseudo-élément. De même, l'élément ciblé par ce pseudo-élément est passé de <content à <slot> dans la dernière version de la spécification du Shadow DOM . Vous pouvez voir une discussion connexe sur ce changement ici .

Actuellement, les navigateurs prennent en charge <content> et ::content.


Réponse originale:


Résumé:

::content est essentiellement un moyen de creuser plus profondément et de styliser les descendants des ShadowHost, qui ne sont normalement pas disponibles pour être stylisés, car votre CSS ne sait pas rechercher le fragment ShadowDOM sans ::content.


Cette réponse suppose que vous connaissez au moins quelque peu le <template> élément et composants Web, en particulier l'élément ShadowDOM, qui traite des ShadowTrees et de leurs deux éléments principaux, ShadowHost et ShadowRoot.

Remarque - Au moment de la rédaction de ce document, il existe moins de 50% de prise en charge (même la prise en charge préfixée, désactivée par défaut) pour les composants Web dans les cinq principaux navigateurs. Bien que tous les navigateurs modernes prennent en charge <template>, seules les versions récentes de Chrome et Opera prennent entièrement en charge ShadowDOM; Firefox prend en charge certaines parties après avoir basculé la fonction requise dans about:config (dom.webcomponents.enabled) à vrai .

Le but de l'utilisation de ShadowDOM est similaire à celui de MVC séparation des préoccupations. Autrement dit, nous voulons séparer notre contenu de notre présentation et permettre des modèles encapsulés dans notre code pour le rendre plus gérable. Nous l'avons déjà dans divers langages de programmation, mais cela est resté un problème pendant un certain temps en HTML et CSS. De plus, il peut y avoir des conflits avec les noms de classe lors du style des éléments dans les applications Web.

Normalement, nous interagissons avec le LightDOM (une sorte de "royaume léger"), mais parfois il serait utile de profiter de l'encapsulation. Le passage dans ce type de "domaine fantôme" (partie des composants Web) est une nouvelle méthode pour éviter les problèmes mentionnés ci-dessus en permettant l'encapsulation . Tous les styles appliqués au balisage dans votre ShadowTree ne s'appliqueront pas au balisage en dehors de votre ShadowTree, même si les mêmes classes ou sélecteurs sont utilisés.

Lorsque le ShadowTree (qui vit dans le ShadowDOM) a un arbre du LightDOM distribué en son sein, et/ou lorsque le ShadowTree est rendu, le le résultat est converti par le navigateur en ce qu'on appelle un arbre composé.

Lorsque le navigateur rend votre code, le contenu est distribué et inséré à de nouveaux emplacements autre que où il a été physiquement tapé. Cette sortie distribuée est ce que vous voyez (et ce que le navigateur voit), et s'appelle composed tree. En réalité, le contenu n'est pas tapé à l'origine dans l'ordre où il apparaît maintenant, mais vous ne le saurez pas, et le navigateur non plus. Cette séparation entre "résultat final" et "code d'origine", si vous voulez, est l'un des principaux avantages de l'encapsulation.

Web Components & the Future of CSS est une excellente vidéo de 40 minutes sur les composants Web et en particulier le ShadowDOM, souligné à moi par ZachSaucier .


Spécifique à votre question, le ::content le pseudo-élément s'applique à ce qu'on appelle nœuds distribués . Un nœud distribué est un autre terme pour tout ce que vous mettez dans le <content></content> Mots clés. Le contenu est distribué de sa place dans le balisage d'origine jusqu'à l'endroit où vous avez placé votre <content> balises dans le modèle.

Ainsi, lorsque vous avez besoin de spécificité en CSS, vous pouvez normalement gérer les sélecteurs en allant à l'élément parent et en l'ajoutant dans le sélecteur. Ex: si .container {} n'est pas assez spécifique, vous pouvez utiliser div .container {} ou .main .container {} afin de faire fonctionner votre sélecteur.

En pensant au point de ShadowDOM, qui est la portée et l'encapsulation, vous devez vous rendre compte que ce nouveau ShadowTree que vous avez créé est un tout nouveau fragment DOM (discret). Ce n'est pas dans le même "royaume léger" que le reste de votre contenu; c'est dans un "royaume des ombres". Alors, comment le CSS sait-il cibler ce "royaume des ombres"? En utilisant le ::content pseudo-élément!

Le ::content le sélecteur de pseudo-élément agit comme l'élément parent des nœuds distribués.

HTML5Rocks a une grande séquence de tutoriels ici , ici , et ici qui couvrent plus d'informations et donnent de bons exemples (assurez-vous de visiter avec = Chrome ou Opera jusqu'à ce que plus de navigateurs prennent en charge ces fonctionnalités).

Par exemple, consultez cette version modifiée et améliorée (par Leo ) du code de HTML5Rocks:

var div = document.querySelector('div');
var root = div.createShadowRoot();
var template = document.querySelector('template');

root.appendChild(template.content);
<template>
  <style>
    h3 { color: red; }
    content[select="h3"]::content > h3 { color: green; }
    ::content section p { text-decoration: underline; }
  </style>
  <h3>Shadow DOM</h3>
  <content select="h3"></content>
  <content select="section"></content>
</template>

<div>
  <h3>Light DOM</h3>
  <section>
    <div>I'm not underlined</div>
    <p>I'm underlined in Shadow DOM!</p>
  </section>
</div>

Également disponible sur JSFiddle (N'oubliez pas de visiter dans un navigateur WebKit comme Chrome ou Opera)

Ici, vous pouvez voir que le ::contentsection p le pseudo-élément est d'abord sélection du contenu de ShadowRoot, qui est le contenu de l'élément div dans votre balisage, et puis préciser davantage en ajoutant section p.

Cela peut sembler inutile par rapport à l'utilisation normale du sélecteur CSS (par exemple, pourquoi ne pas simplement utiliser section p {}?), jusqu'à ce que vous vous souveniez que, lors de la traversée d'un ShadowTree, vous ne pouvez normalement pas sélectionner les descendants des éléments Host (qui sont les nœuds distribués), car ils se trouvent dans le "Shadow Realm" I mentionné plus tôt.

107
TylerH

Dommage! Malheureusement ::content est v0 , et a été déconseillé.

Vous devez maintenant utiliser la v1 ::slotted.

Aussi, <content> a été déconseillé au profit de <slot>.

Veuillez voir: http://hayato.io/2016/shadowdomv1/

Voir aussi: Composants Web - pourquoi <content> a été remplacé par <slot>

5
MarcG