Le composant Web HTML n'utilise pas le style Shadow DOM
J'ai créé un composant Web vanille ou un élément HTML. Il affiche simplement deux liens.
Pour encapsuler la chose, j'utilise shadow DOM. Cependant, il ne semble pas être encapsulé. Dans l'arborescence DOM, c'est à l'intérieur de # shadow-root, ce qui est bien.
Pourquoi le composant Web utilise-t-il le style global au lieu du style que j'ai fourni dans le modèle pour mon composant Web?
Le texte est rouge et je m'attendais à ce qu'il soit vert.
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>
Réponses
Bien que cette question ait déjà une réponse acceptée, déplacer les enfants d'un emplacement vers le shadowRoot n'est pas souhaitable dans la plupart des cas d'utilisation.
Ce que vous souhaitez probablement faire est d'utiliser le ::slotted()
sélecteur.
Gardez simplement à l'esprit que les styles appliqués aux enfants d'un slot via le ::slotted()
sélecteur agissent uniquement comme des styles "par défaut" et peuvent toujours être remplacés en utilisant des styles dans le DOM léger.
Par exemple, vérifiez cette version modifiée de votre extrait de code:
Comme vous pouvez le voir, cette fois my-el
essaie d'appliquer à la fois une couleur et un style de décoration de texte aux <a>
enfants d' ancrage ( ) dans l'un de ses emplacements.
Cependant, en lumière dom, nous avons un a.special
sélecteur qui remplace la couleur, donc le <a class="special">
sera rouge, pas vert
class MyEl extends HTMLElement {
constructor() {
super();
this.shadow = this.attachShadow({ mode: "open" });
}
connectedCallback() {
const template = `
<style>
::slotted(a) {
color: green;
text-decoration: none;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = template;
}
}
window.customElements.define("my-el", MyEl);
a.special {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a class="special" href="example.com">Item2</a>
</my-el>
L'explication complète et détaillée est dans: :: sélecteur CSS fendu pour les enfants imbriqués dans le slot shadowDOM
TL; DR
Vos liens sont dans lightDOM et donc stylisés par son DOM (dans votre code le document DOM)
Déplacer les nœuds de lightDOM vers shadowDOM est une "solution"; mais vous n'utilisez pas de slots alors.
Pour info, votre code peut être compacté en:
class MyEl extends HTMLElement {
constructor() {
super().attachShadow({ mode: "open" })
.innerHTML = `<style>a{color:green}</style><slot></slot>`;
}
}
window.customElements.define("my-el", MyEl);
Vous trouverez plus de réponses liées aux SLOT avec StackOverflow Search: SLOTs d'éléments personnalisés
observez cette ligne, vous devez déplacer / copier des éléments à ombrer par exemple avec:
this.shadow.innerHTML = this.innerHTML + template;
J'ai ajouté ceci pour démontrer que seul le style en ligne sera appliqué aux éléments shadow dom .. donc les liens copiés dans SD utilisent votre style :)
donc le rouge sera GLOBAL
, le vert sera des SHADOW
éléments
class MyEl extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
this.shadow = this.attachShadow({ mode: "open" });
const template = `
<style>
a {
color: green;
}
</style>
<slot></slot>`;
this.shadow.innerHTML = this.innerHTML + template;
}
}
window.customElements.define("my-el", MyEl);
a {
color: red
}
<my-el>
<a href="example.com">Item1</a>
<a href="example.com">Item2</a>
</my-el>