Start · Sprachen · JavaScript · Referenz · Element.shadowRoot

Element.shadowRoot

Eigenschaft

Liefert den <code>ShadowRoot</code> eines Elements, sofern er im Modus <code>"open"</code> angehängt wurde, sonst <code>null</code>.

seit JavaScript Baseline: alle modernen Browser (seit 2020) Kategorie: webapi

Signatur

get Element.shadowRoot

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: shadowRoot liefert das ShadowRoot-Objekt.
  • Mit mode: "closed" erzeugt: shadowRoot liefert null. Nur die Referenz, die attachShadow() 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

Typ
ShadowRoot | null
Beschreibung
Der offene 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);
null true Hallo aus dem Shadow DOM

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);
Anna

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);
true null closed

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 shadowRoot hat keine Wirkung. Im Strict Mode wird ein TypeError geworfen. Einen Shadow-Root legt man ausschließlich mit attachShadow() oder deklarativ an.
  • Geschlossener Modus ist kein Sicherheitsmerkmal: mode: "closed" verhindert nur den bequemen Zugriff über shadowRoot. Fremdes Skript auf derselben Seite kann zum Beispiel attachShadow überschreiben und die Referenz abgreifen. Für echte Isolation eignen sich iframes oder Origins.
  • Bei Custom Elements mit geschlossenem Shadow-Root stellt ElementInternals.shadowRoot (über attachInternals()) 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 wie div, span, section, article, p oder body. Bei anderen, etwa input oder img, wirft es eine NotSupportedError-DOMException.
  • Browser-interne Shadow-Bäume (etwa von <video>-Steuerelementen) sind über shadowRoot nicht erreichbar, der Wert ist dort null.
  • document.querySelector() durchsucht keine Shadow-Bäume. Dafür muss man gezielt über shadowRoot hineingehen.
  • 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.