Signatur
Beschreibung
createContextualFragment() nimmt einen Markup-String entgegen und liefert daraus ein DocumentFragment, das noch nicht im Dokument hängt. Der Parser arbeitet dabei im Kontext des Startknotens des Range: Ist das ein Element, wird der String so geparst, als wäre er dessen innerHTML. Ist der Startknoten ein Text- oder Kommentarknoten, zählt dessen Elternelement. Fehlt ein passendes Element (etwa beim Startknoten document) oder ist es das <html>-Element, parst der Browser in HTML-Dokumenten im Kontext von <body>.
Wichtig ist der Kontext bei Markup, das nur in bestimmten Elternelementen gültig ist, zum Beispiel <tr>, <td> oder <option>. Setzt man den Range per selectNodeContents() in ein <tbody>, bleiben Tabellenzeilen erhalten. Im Body-Kontext würde der Parser sie verwerfen.
Anders als bei innerHTML oder <template> werden <script>-Elemente aus dem Fragment ausgeführt, sobald man das Fragment ins Dokument einfügt. Das ist nützlich, wenn man per fetch geladene HTML-Schnipsel mitsamt Skripten einbinden will, etwa Widgets oder Einbettungscode von Drittanbietern. Genau deshalb ist die Methode aber auch ein Sicherheitsrisiko, wenn die Eingabe nicht vertrauenswürdig ist.
Das Fragment lässt sich vor dem Einfügen noch per DOM-API bearbeiten, zum Beispiel mit querySelector. Danach fügt man es mit append(), insertBefore() oder range.insertNode() in einem Schritt ein. Beim Einfügen wird das Fragment geleert, seine Kindknoten landen im Ziel.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $tagString Pflicht | string | TrustedHTML | Der zu parsende HTML- bzw. XML-String. Wenn per CSP require-trusted-types-for 'script' erzwungen wird, muss ein TrustedHTML-Objekt übergeben werden. |
Rückgabewert
DocumentFragment mit den geparsten Knoten. Enthaltene <script>-Elemente werden beim Einfügen ins Dokument ausgeführt.Beispiele
HTML-String in ein Element einfügen
const container = document.querySelector('#news');
const range = document.createRange();
range.selectNodeContents(container);
const fragment = range.createContextualFragment(
'<article><h2>Update</h2><p>Version 2.0 ist da.</p></article>'
);
console.log(fragment.childNodes.length);
container.append(fragment);
console.log(fragment.childNodes.length); // Fragment ist nach dem Einfügen leer
Tabellenzeilen im richtigen Kontext parsen
const tbody = document.querySelector('#users tbody');
const range = document.createRange();
range.selectNodeContents(tbody); // Kontext = <tbody>
const users = [{ name: 'Anna', role: 'Admin' }, { name: 'Ben', role: 'Autor' }];
// Achtung: Werte hier fest vorgegeben – Nutzereingaben vorher escapen!
const rows = users
.map((u) => `<tr><td>${u.name}</td><td>${u.role}</td></tr>`)
.join('');
const fragment = range.createContextualFragment(rows);
console.log(fragment.querySelectorAll('tr').length);
tbody.append(fragment);
Nachgeladenes HTML mit ausführbarem Skript einbinden
const loadWidget = async (url, target) => {
const html = await (await fetch(url)).text();
const range = document.createRange();
range.selectNodeContents(target);
const fragment = range.createContextualFragment(html);
target.replaceChildren(fragment); // <script>-Tags laufen jetzt
};
// Vergleich: innerHTML führt Skripte NICHT aus
const box = document.createElement('div');
document.body.append(box);
box.innerHTML = '<script>console.log("innerHTML")<\/script>';
const frag = document.createRange().createContextualFragment(
'<script>console.log("createContextualFragment")<\/script>'
);
document.body.append(frag);
// Wichtig · Fallstricke
Sicherheit (XSS): Skripte im Fragment werden beim Einfügen ausgeführt. Außerdem feuern Inline-Event-Handler wie <img src=x onerror="…">. Die Methode ist damit gefährlicher als innerHTML. Übergib niemals ungeprüfte Nutzereingaben oder Antworten fremder Server. Bereinige den String mit einem Sanitizer (z. B. DOMPurify) oder baue die Knoten direkt per createElement() und textContent.
CSP und Trusted Types: Nachgeladene Skripte unterliegen der Content Security Policy der Seite. Inline-Skripte laufen ohne 'unsafe-inline', Nonce oder Hash nicht. Mit aktivierten Trusted Types wirft die Methode bei einem normalen String einen TypeError.
Kontext: Ein frischer Range aus document.createRange() beginnt beim document. Geparst wird dann im Body-Kontext, und kontextabhängiges Markup wie <tr> oder <td> geht dabei verloren. Setze den Range deshalb vorher auf das passende Element.
Kompatibilität: Die Methode wird von allen modernen Browsern unterstützt. In Node.js gibt es sie nicht nativ, nur über DOM-Implementierungen wie jsdom. Wer nur statisches Markup ohne Skripte braucht, kann alternativ <template> oder DOMParser verwenden. Dort werden Skripte nicht ausgeführt.