Die HTML-Webkomponente verwendet keinen Schatten-DOM-Stil
Ich habe eine Vanille-Webkomponente oder ein HTML-Element erstellt. Es werden nur zwei Links angezeigt.
Um das Ding zu kapseln, benutze ich Shadow DOM. Es scheint jedoch nicht gekapselt zu sein. Im DOM-Baum befindet es sich in # shadow-root, was gut ist.
Warum verwendet die Webkomponente den globalen Stil anstelle des Stils, den ich in der Vorlage für meine Webkomponente angegeben habe?
Der Text ist rot und ich habe erwartet, dass er grün ist.
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>
Antworten
Während diese Frage bereits eine akzeptierte Antwort hat, ist es für die meisten Anwendungsfälle nicht wünschenswert, die untergeordneten Elemente eines Slots in den shadowRoot zu verschieben.
Was Sie wahrscheinlich tun möchten, ist die Verwendung des ::slotted()
Selektors.
Denken Sie daran, dass Stile, die über die ::slotted()
Auswahl auf die untergeordneten Elemente eines Slots angewendet werden, nur als "Standard" -Stile fungieren und dennoch durch die Verwendung von Stilen in Light DOM überschrieben werden können.
Überprüfen Sie beispielsweise diese bearbeitete Version Ihres Snippets:
Wie Sie sehen können, wird dieses Mal my-el
versucht, sowohl einen Farb- als auch einen Textdekorationsstil auf verankerte ( <a>
) Kinder in einem der Slots anzuwenden .
In Light Dom haben wir jedoch einen a.special
Selektor, der die Farbe überschreibt, sodass die Farbe <a class="special">
rot und nicht grün ist
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>
Die vollständige, detaillierte Erklärung finden Sie in: :: CSS-Selektor mit Schlitz für verschachtelte Kinder im ShadowDOM-Slot
TL; DR
Ihre Links befinden sich in lightDOM und werden daher durch das DOM (in Ihrem Code das Dokument-DOM) gestaltet. Das
Verschieben der Knoten von lightDOM nach shadowDOM ist eine "Lösung". Dann verwenden Sie jedoch keine Slots.
Zu Ihrer Information, Ihr Code kann komprimiert werden zu:
class MyEl extends HTMLElement {
constructor() {
super().attachShadow({ mode: "open" })
.innerHTML = `<style>a{color:green}</style><slot></slot>`;
}
}
window.customElements.define("my-el", MyEl);
Weitere SLOT-bezogene Antworten finden Sie mit StackOverflow Search: Custom Elements SLOTs
Beachten Sie diese Linie, Sie müssen Elemente verschieben / kopieren, um sie zu schattieren, zum Beispiel mit:
this.shadow.innerHTML = this.innerHTML + template;
Ich habe dies hinzugefügt, um zu demonstrieren, dass nur Inline-Stil auf Shadow-Dom-Elemente angewendet wird. Kopierte Links in SD verwenden also Ihren Stil :)
So wird Rot sein GLOBAL
, Grün wird SHADOW
Elemente sein
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>