Signatur
Beschreibung
setHTML() ist Teil der HTML Sanitizer API. Die Methode parst einen HTML-String, bereinigt das Ergebnis mit einem Sanitizer und ersetzt anschließend alle bisherigen Kindknoten des ShadowRoot durch das Ergebnis. Damit ist sie die sichere Alternative zu shadowRoot.innerHTML = ..., wenn du Markup aus nicht vertrauenswürdigen Quellen (Benutzereingaben, CMS-Inhalte, API-Antworten) in einer Web Component darstellen willst.
Die Methode ist immer XSS-sicher: Selbst wenn eine eigene Sanitizer-Konfiguration z. B. <script> oder onclick ausdrücklich erlaubt, entfernt setHTML() solche gefährlichen Elemente und Attribute (Event-Handler, javascript:-URLs usw.) trotzdem. Ohne Optionen wird die eingebaute Standardkonfiguration genutzt, die zusätzlich z. B. Kommentare, <iframe> oder <embed> entfernt.
Über options.sanitizer kannst du die Filterung weiter einschränken bzw. anpassen: entweder mit einer Sanitizer-Instanz, einem SanitizerConfig-Objekt (z. B. { elements: [...] }, removeElements, attributes, removeAttributes, replaceWithChildrenElements, comments, dataAttributes) oder dem String "default". Brauchst du tatsächlich Skripte oder Declarative Shadow DOM, ist setHTMLUnsafe() das (bewusst unsichere) Gegenstück.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $input Pflicht | string | Der zu parsende HTML-String. Er wird wie im Body-Kontext geparst und anschließend bereinigt. | |
| $options | object | {} | Optionsobjekt. Einzige Eigenschaft: sanitizer. |
| $options.sanitizer | Sanitizer | SanitizerConfig | "default" | "default" | Legt fest, welche Elemente und Attribute erhalten bleiben. Unsichere Inhalte werden unabhängig von dieser Einstellung immer entfernt. |
Rückgabewert
Beispiele
Benutzer-HTML sicher in eine Web Component rendern
class UserComment extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open' });
}
set content(html) {
// Standardkonfiguration: Skripte, Event-Handler & Co. fliegen raus
this.shadowRoot.setHTML(html);
}
}
customElements.define('user-comment', UserComment);
const el = document.createElement('user-comment');
document.body.append(el);
el.content = '<p onclick="alert(1)">Hallo <b>Welt</b></p><script>alert(2)</script>';
console.log(el.shadowRoot.innerHTML);
Erlaubte Elemente per SanitizerConfig einschränken
const host = document.querySelector('#preview');
const shadow = host.shadowRoot ?? host.attachShadow({ mode: 'open' });
const markdownHtml = '<h1>Titel</h1><p>Text mit <a href="https://example.com" style="color:red">Link</a></p><img src="x.png">';
shadow.setHTML(markdownHtml, {
sanitizer: {
elements: ['p', 'a', 'strong', 'em'],
attributes: ['href']
}
});
console.log(shadow.innerHTML);
Wiederverwendbare Sanitizer-Instanz
const sanitizer = new Sanitizer();
sanitizer.removeElement('img');
sanitizer.removeAttribute('class');
const shadow = document.querySelector('#card').attachShadow({ mode: 'open' });
shadow.setHTML('<div class="x"><img src="a.png">Karte</div>', { sanitizer });
console.log(shadow.innerHTML);
Feature-Erkennung mit Fallback
const renderSafe = (shadowRoot, html) => {
if ('setHTML' in ShadowRoot.prototype) {
shadowRoot.setHTML(html);
} else {
// Fallback: nur Text, niemals ungeprüft innerHTML verwenden
shadowRoot.textContent = html;
// oder eine Bibliothek wie DOMPurify einsetzen
}
};
const root = document.body.appendChild(document.createElement('div')).attachShadow({ mode: 'open' });
renderSafe(root, '<em>sicher</em><script>boom()</script>');
// Wichtig · Fallstricke
- Kompatibilität: Die Sanitizer API ist noch experimentell. Firefox liefert sie ab Version 148 aus, in Chromium-Browsern ist sie derzeit nur hinter einem Flag verfügbar, Safari unterstützt sie noch nicht. Mach vorher eine Feature-Erkennung (
'setHTML' in ShadowRoot.prototype) und nutze als Fallback z. B. DOMPurify. - Ältere Spezifikation: Frühe Implementierungen (Chrome 105–118 mit Flag) hatten eine abweichende API (
Element.setHTML()mit andererSanitizer-Konfiguration). Code aus alten Tutorials funktioniert daher oft nicht mehr. - Ersetzt alles: Alle vorhandenen Kindknoten des Shadow Roots, auch
<style>-Elemente, werden entfernt. Styles lassen sich besser überadoptedStyleSheetseinbinden, dann bleiben sie erhalten. - Kein Declarative Shadow DOM:
<template shadowrootmode>wird nicht in verschachtelte Shadow Roots umgewandelt. Dafür gibt es nursetHTMLUnsafe(). - Sicherheit:
setHTML()verhindert Skriptausführung, aber keine anderen Angriffe wie CSS-basiertes Datenabgreifen oder Phishing über Formulare und Links. Beschränke daher die erlaubten Elemente und Attribute mit einer eigenen Konfiguration so weit wie möglich. Mit Trusted Types giltsetHTML()als sicherer Einstiegspunkt und braucht keine Policy.