Signatur
Beschreibung
Die schreibgeschützte Eigenschaft Element.shadowRoot gibt den Shadow-Root zurück, den ein Element als Shadow-Host trägt. Über diesen ShadowRoot erreicht man den gekapselten Shadow-DOM-Baum, zum Beispiel um darin Elemente zu suchen, Inhalte zu aktualisieren oder Styles einzufügen.
Ob ein Wert zurückkommt, hängt davon ab, wie der Shadow-Root angelegt wurde:
- Mit
attachShadow({ mode: "open" })erzeugt:shadowRootliefert dasShadowRoot-Objekt. - Mit
mode: "closed"erzeugt:shadowRootliefertnull. Nur die Referenz, dieattachShadow()zurückgegeben hat, bietet dann Zugriff. - Kein Shadow-Root vorhanden:
null.
Typische Einsatzfälle sind Web Components, die intern über this.shadowRoot auf ihr eigenes Template zugreifen, außerdem Tests und Debugging-Werkzeuge, die in offene Shadow-Bäume hineinschauen müssen. Das gilt auch für Shadow-Roots, die deklarativ über <template shadowrootmode="open"> im HTML entstanden sind.
Rückgabewert
ShadowRoot des Elements, oder null, wenn keiner existiert oder er im Modus "closed" angelegt wurde.Beispiele
Shadow-Root anhängen und über shadowRoot abfragen
const host = document.createElement('div');
document.body.append(host);
console.log(host.shadowRoot); // noch kein Shadow-Root
host.attachShadow({ mode: 'open' });
host.shadowRoot.innerHTML = '<p>Hallo aus dem Shadow DOM</p>';
console.log(host.shadowRoot instanceof ShadowRoot);
console.log(host.shadowRoot.querySelector('p').textContent);
Web Component aktualisiert ihr Template über this.shadowRoot
class UserBadge extends HTMLElement {
static observedAttributes = ['name'];
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = `
<style>span { font-weight: bold; color: teal; }</style>
Benutzer: <span></span>
`;
}
attributeChangedCallback(name, oldValue, newValue) {
this.shadowRoot.querySelector('span').textContent = newValue;
}
}
customElements.define('user-badge', UserBadge);
const badge = document.createElement('user-badge');
badge.setAttribute('name', 'Anna');
document.body.append(badge);
console.log(badge.shadowRoot.querySelector('span').textContent);
Unterschied zwischen offenem und geschlossenem Modus
const offen = document.createElement('div');
const geschlossen = document.createElement('div');
offen.attachShadow({ mode: 'open' });
const privaterRoot = geschlossen.attachShadow({ mode: 'closed' });
console.log(offen.shadowRoot !== null);
console.log(geschlossen.shadowRoot);
// Zugriff nur über die gespeicherte Referenz
console.log(privaterRoot.mode);
Alle offenen Shadow-Roots rekursiv durchsuchen (z. B. in Tests)
const queryDeep = (root, selector) => {
const treffer = [...root.querySelectorAll(selector)];
for (const el of root.querySelectorAll('*')) {
if (el.shadowRoot) {
treffer.push(...queryDeep(el.shadowRoot, selector));
}
}
return treffer;
};
const buttons = queryDeep(document, 'button');
console.log(`${buttons.length} Buttons gefunden (inkl. Shadow DOM)`);
// Wichtig · Fallstricke
- Schreibgeschützt: Eine Zuweisung an
shadowRoothat keine Wirkung. Im Strict Mode wird einTypeErrorgeworfen. Einen Shadow-Root legt man ausschließlich mitattachShadow()oder deklarativ an. - Geschlossener Modus ist kein Sicherheitsmerkmal:
mode: "closed"verhindert nur den bequemen Zugriff übershadowRoot. Fremdes Skript auf derselben Seite kann zum BeispielattachShadowüberschreiben und die Referenz abgreifen. Für echte Isolation eignen sich iframes oder Origins. - Bei Custom Elements mit geschlossenem Shadow-Root stellt
ElementInternals.shadowRoot(überattachInternals()) den Zugriff für die Komponente selbst bereit. - Nicht jedes Element kann Shadow-Host sein.
attachShadow()funktioniert nur bei autonomen Custom Elements und bestimmten Elementen wiediv,span,section,article,poderbody. Bei anderen, etwainputoderimg, wirft es eineNotSupportedError-DOMException. - Browser-interne Shadow-Bäume (etwa von
<video>-Steuerelementen) sind übershadowRootnicht erreichbar, der Wert ist dortnull. document.querySelector()durchsucht keine Shadow-Bäume. Dafür muss man gezielt übershadowRoothineingehen.- Kompatibilität: In Chrome, Edge, Firefox und Safari unterstützt (Shadow DOM v1). Den deklarativen Shadow DOM (
shadowrootmode) gibt es erst in neueren Versionen, seit 2024 in allen großen Browsern.