El componente web HTML no usa el estilo DOM de sombra
He creado un componente web vanilla o un elemento HTML. Solo muestra dos enlaces.
Para encapsular la cosa, uso shadow DOM. Sin embargo, no parece estar encapsulado. En el árbol DOM está dentro de # shadow-root, lo cual es bueno.
¿Por qué el componente web usa el estilo global en lugar del estilo que proporcioné en la plantilla para mi componente web?
El texto es rojo y esperaba que fuera verde.
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>
Respuestas
Si bien esta pregunta ya tiene una respuesta aceptada, mover los hijos de una ranura a shadowRoot no es deseable para la mayoría de los casos de uso.
Lo que probablemente quieras hacer es usar el ::slotted()
selector.
Solo tenga en cuenta que los estilos aplicados a los hijos de un espacio a través del ::slotted()
selector solo actúan como estilos "predeterminados" y aún pueden anularse usando estilos en DOM ligero.
Por ejemplo, consulte esta versión editada de su fragmento:
Como puede ver, esta vez my-el
intenta aplicar un color y un estilo de decoración de texto para anclar ( <a>
) a los niños en cualquiera de sus espacios.
Sin embargo, en light dom, tenemos un a.special
selector que anula el color, por lo <a class="special">
que será rojo, no verde.
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>
La explicación completa y detallada se encuentra en: :: selector CSS ranurado para niños anidados en la ranura shadowDOM
TL; DR
Sus enlaces están en lightDOM y por lo tanto están diseñados por su DOM (en su código el documento DOM).
Mover los nodos de lightDOM a shadowDOM es una "solución"; pero entonces no estás usando ranuras.
Para su información, su código se puede compactar para:
class MyEl extends HTMLElement {
constructor() {
super().attachShadow({ mode: "open" })
.innerHTML = `<style>a{color:green}</style><slot></slot>`;
}
}
window.customElements.define("my-el", MyEl);
Se pueden encontrar más respuestas relacionadas con SLOT con StackOverflow Search: SLOT de elementos personalizados
observe esta línea, debe mover / copiar elementos para sombrear, por ejemplo con:
this.shadow.innerHTML = this.innerHTML + template;
Agregué esto para demostrar que solo se aplicará el estilo en línea a los elementos de dom de sombra ... así que los enlaces copiados en SD están usando su estilo :)
así que el rojo será GLOBAL
, el verde será SHADOW
elementos

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>