Start · Sprachen · JavaScript · Referenz · ShadowRoot.innerHTML

ShadowRoot.innerHTML

Eigenschaft

Liest oder setzt das HTML-Markup des DOM-Baums innerhalb eines <code>ShadowRoot</code> als String.

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

Signatur

ShadowRoot.innerHTML

Beschreibung

Die Eigenschaft innerHTML eines ShadowRoot funktioniert wie Element.innerHTML, bezieht sich aber auf den gesamten Inhalt des Schattenbaums. Beim Lesen bekommst du den serialisierten HTML-Inhalt aller Kindknoten des Shadow Roots, beim Schreiben wird der vorhandene Inhalt komplett entfernt und durch die geparsten Knoten aus dem übergebenen String ersetzt.

Typischerweise nutzt man sie in Web Components, um direkt nach attachShadow() ein Template mit Markup und <style>-Block in den Schattenbaum zu schreiben. Styles darin sind gekapselt, gelten also nur innerhalb der Komponente und werden nicht nach außen weitergegeben.

Wichtig: Das Setzen erzeugt jedes Mal neue Knoten. Event-Listener, Zustände von Formularfeldern und Referenzen auf alte Knoten gehen verloren. Für häufige, kleine Änderungen solltest du deshalb lieber gezielt einzelne Knoten bearbeiten (textContent, replaceChildren(), append()).

Parameter

Name Typ Default Beschreibung
$value string Nur beim Setzen: HTML-String, der geparst wird und den gesamten Inhalt des Shadow Roots ersetzt. Ein leerer String entfernt alle Kinder.

Rückgabewert

Typ
string
Beschreibung
Das serialisierte HTML aller Kindknoten des ShadowRoot. Ist der Schattenbaum leer, ist es ein leerer String.

Beispiele

Web Component mit gekapseltem Markup und Styles

class HalloKarte extends HTMLElement {
  constructor() {
    super();
    const shadow = this.attachShadow({ mode: 'open' });
    shadow.innerHTML = `
      <style>
        .karte { padding: 1rem; border: 1px solid #ccc; border-radius: 8px; }
      </style>
      <div class="karte"><slot>Standardtext</slot></div>
    `;
  }
}
customElements.define('hallo-karte', HalloKarte);

document.body.innerHTML = '<hallo-karte>Willkommen!</hallo-karte>';

Inhalt des Shadow Roots auslesen

const host = document.createElement('div');
const root = host.attachShadow({ mode: 'open' });
root.innerHTML = '<p>Hallo <b>Welt</b></p>';

console.log(root.innerHTML);
console.log(host.innerHTML === ''); // Light DOM bleibt leer
<p>Hallo <b>Welt</b></p> true

Nutzereingaben sicher einfügen

const root = document.createElement('div').attachShadow({ mode: 'open' });
const benutzername = '<img src=x onerror=alert(1)>';

// Unsicher: root.innerHTML = `<p>Hallo ${benutzername}</p>`;
// Sicher: Struktur per innerHTML, Daten per textContent
root.innerHTML = '<p>Hallo <span class="name"></span></p>';
root.querySelector('.name').textContent = benutzername;

console.log(root.innerHTML);
<p>Hallo <span class="name">&lt;img src=x onerror=alert(1)&gt;</span></p>

Shadow Root leeren

const root = document.createElement('div').attachShadow({ mode: 'open' });
root.innerHTML = '<ul><li>A</li><li>B</li></ul>';
console.log(root.childNodes.length);

root.innerHTML = '';
console.log(root.childNodes.length);
1 0

// Wichtig · Fallstricke

Sicherheit (XSS): Wie bei Element.innerHTML wird der String als HTML geparst. Ungeprüfte Nutzereingaben können Event-Handler-Attribute wie onerror einschleusen. <script>-Elemente, die über innerHTML eingefügt werden, laufen zwar nicht, Inline-Handler dagegen schon. Setze Daten deshalb per textContent oder bereinige sie vorher, etwa mit DOMPurify. Bei aktiven Trusted Types (CSP require-trusted-types-for 'script') muss ein TrustedHTML-Objekt übergeben werden, ein einfacher String löst sonst einen TypeError aus.

  • Beim Setzen werden alle bisherigen Knoten samt Event-Listenern ersetzt. Gespeicherte Referenzen zeigen danach auf Knoten, die nicht mehr im Baum hängen.
  • Declarative Shadow DOM (<template shadowrootmode>) wird über innerHTML nicht ausgewertet. Dafür gibt es setHTMLUnsafe().
  • Bei mode: 'closed' ist element.shadowRoot null. Den Zugriff hast du dann nur über die Referenz, die attachShadow() zurückgibt.
  • Browser-Unterstützung: Chrome/Edge 53+, Firefox 63+, Safari 10+.