Signatur
Beschreibung
attachShadow() erzeugt für ein Element (den Shadow Host) einen eigenen, vom übrigen Dokument abgekapselten DOM-Teilbaum. Markup und Styles in diesem Shadow DOM werden nicht von den Selektoren und CSS-Regeln der umgebenden Seite erfasst, und umgekehrt gelangen Styles aus dem Shadow DOM nicht nach außen. Das ist die Grundlage für wiederverwendbare Web Components, deren Aussehen und Verhalten nicht durch fremden Code zerstört werden kann.
Üblicherweise wird die Methode im Konstruktor eines Custom Elements aufgerufen (this.attachShadow({ mode: 'open' })). Der Inhalt der Light-DOM-Kinder des Hosts lässt sich über <slot>-Elemente in den Shadow-Baum projizieren.
Über die Option mode legt man fest, ob der Shadow Root von außen über element.shadowRoot erreichbar ist ('open') oder nicht ('closed'). Weitere Optionen steuern Fokus-Delegation, Slot-Zuweisung, Klonbarkeit und Serialisierbarkeit.
Nicht jedes Element kann einen Shadow Root erhalten: erlaubt sind autonome Custom Elements (mit gültigem Namen) sowie article, aside, blockquote, body, div, footer, h1–h6, header, main, nav, p, section und span.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $options Pflicht | Object | Konfigurationsobjekt für den Shadow Root. | |
| $options.mode Pflicht | 'open' | 'closed' | 'open': Shadow Root über element.shadowRoot erreichbar. 'closed': element.shadowRoot liefert null; nur die zurückgegebene Referenz erlaubt Zugriff. |
|
| $options.delegatesFocus | boolean | false | Bei true wird ein Klick auf nicht fokussierbare Teile des Hosts an das erste fokussierbare Element im Shadow DOM weitergeleitet; der Host erhält :focus-Styling. |
| $options.slotAssignment | 'named' | 'manual' | 'named' | 'named': automatische Zuweisung über das slot-Attribut. 'manual': Zuweisung per HTMLSlotElement.assign(). |
| $options.clonable | boolean | false | Bei true wird der Shadow Root beim cloneNode() bzw. importNode() des Hosts mitkopiert. |
| $options.serializable | boolean | false | Bei true kann der Shadow Root mit getHTML({ serializableShadowRoots: true }) serialisiert werden. |
Rückgabewert
ShadowRoot, in den Inhalte (z. B. per innerHTML, append()) eingefügt werden können.Beispiele
Shadow DOM an ein div anhängen
const host = document.createElement('div');
document.body.append(host);
const shadow = host.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>p { color: crimson; }</style>
<p>Ich bin gekapselt.</p>
`;
// Globale <p>-Styles wirken hier nicht – und crimson wirkt nicht außerhalb
console.log(host.shadowRoot === shadow);
console.log(document.querySelector('p')); // Shadow-Inhalt ist nicht sichtbar
Web Component mit Slot
class InfoBox extends HTMLElement {
constructor() {
super();
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
:host { display: block; border: 1px solid #0a7; padding: .5rem; }
h2 { margin: 0; font-size: 1rem; }
</style>
<h2><slot name="titel">Hinweis</slot></h2>
<slot></slot>
`;
}
}
customElements.define('info-box', InfoBox);
document.body.insertAdjacentHTML('beforeend', `
<info-box>
<span slot="titel">Achtung</span>
Die Wartung beginnt um 22 Uhr.
</info-box>
`);
Geschlossener Shadow Root mit privater Referenz
class SecretCounter extends HTMLElement {
#root;
#count = 0;
constructor() {
super();
this.#root = this.attachShadow({ mode: 'closed', delegatesFocus: true });
this.#root.innerHTML = '<button>0</button>';
this.#root.querySelector('button').addEventListener('click', (e) => {
e.target.textContent = ++this.#count;
});
}
}
customElements.define('secret-counter', SecretCounter);
const el = document.createElement('secret-counter');
document.body.append(el);
console.log(el.shadowRoot);
Fehler bei nicht unterstützten Elementen abfangen
const tryAttach = (el) => {
try {
el.attachShadow({ mode: 'open' });
return 'ok';
} catch (err) {
return err.name;
}
};
console.log(tryAttach(document.createElement('section')));
console.log(tryAttach(document.createElement('img')));
const div = document.createElement('div');
tryAttach(div);
console.log(tryAttach(div)); // zweiter Aufruf
// Wichtig · Fallstricke
- Nur einmal pro Element: Ein zweiter Aufruf wirft einen
NotSupportedError(Ausnahme: ein per deklarativem Shadow DOM erzeugter Root mit gleichemmodewird geleert und zurückgegeben). - Nicht unterstützte Elemente (z. B.
img,input,a,button) sowie angepasste eingebaute Elemente mit ungültigem Namen werfenNotSupportedError. 'closed'ist keine Sicherheitsgrenze: Fremde Skripte können z. B.Element.prototype.attachShadowüberschreiben und die Referenz abgreifen. Für vertrauliche Daten nicht darauf verlassen.- XSS: Shadow DOM schützt nicht vor Skript-Injektion. Nutzerdaten nicht ungefiltert per
shadow.innerHTMLeinfügen – liebertextContentoder DOM-Methoden verwenden. - Events aus dem Shadow DOM werden beim Verlassen retargetiert (
event.targetzeigt auf den Host); eigene Events brauchencomposed: true, um die Grenze zu überschreiten. - Kompatibilität:
modeunddelegatesFocuswerden in allen modernen Browsern unterstützt;slotAssignment,clonableundserializablesind neuer und sollten bei älteren Browsern geprüft werden. Der Internet Explorer unterstützt Shadow DOM nicht.