Signatur
Beschreibung
Der Inhalt eines <template>-Elements wird vom Browser zwar geparst, aber nicht gerendert. Bilder werden nicht geladen, Skripte nicht ausgeführt und Styles nicht angewendet. Die Knoten landen nicht als Kinder des <template>-Elements im DOM. Sie liegen in einem eigenen DocumentFragment, auf das du über content zugreifst.
Das Fragment gehört zu einem separaten, „inerten“ Dokument (dem Template-Contents-Owner-Document). So bleibt die Vorlage vom aktiven Dokument getrennt. Meistens klonst du das Fragment mit template.content.cloneNode(true) oder document.importNode(template.content, true), befüllst die Kopie mit Daten und fügst sie dann ins DOM ein.
Typische Einsatzgebiete:
- wiederkehrende Listeneinträge oder Tabellenzeilen
- Karten und Dialoge
- das Shadow DOM von Web Components
Die Eigenschaft ist schreibgeschützt: Du kannst ihr kein anderes Fragment zuweisen. Das vorhandene Fragment lässt sich aber mit DOM-Methoden verändern.
Rückgabewert
DocumentFragment mit dem Template-Inhalt. Bei jedem Zugriff kommt dasselbe Objekt zurück, keine neue Kopie.Beispiele
Listeneinträge aus einer Vorlage erzeugen
// HTML:
// <ul id="users"></ul>
// <template id="user-row"><li><strong class="name"></strong> – <span class="mail"></span></li></template>
const users = [
{ name: 'Anna', mail: 'anna@example.com' },
{ name: 'Ben', mail: 'ben@example.com' }
];
const tpl = document.querySelector('#user-row');
const list = document.querySelector('#users');
for (const user of users) {
const clone = tpl.content.cloneNode(true); // tiefe Kopie des Fragments
clone.querySelector('.name').textContent = user.name;
clone.querySelector('.mail').textContent = user.mail;
list.append(clone);
}
console.log(list.children.length);
Template-Inhalt ist nicht Teil des DOM
// <template id="t"><p>Hallo</p></template>
const tpl = document.getElementById('t');
console.log(tpl.childNodes.length); // keine direkten Kinder
console.log(tpl.content instanceof DocumentFragment);
console.log(tpl.content.querySelector('p').textContent);
console.log(document.querySelector('p')); // nicht im Dokument auffindbar
Shadow DOM einer Web Component befüllen
const tpl = document.createElement('template');
tpl.innerHTML = `
<style>button { font-weight: bold; }</style>
<button><slot>Klick mich</slot></button>
`;
class FancyButton extends HTMLElement {
constructor() {
super();
const root = this.attachShadow({ mode: 'open' });
root.append(tpl.content.cloneNode(true));
}
}
customElements.define('fancy-button', FancyButton);
document.body.append(document.createElement('fancy-button'));
Knoten aus dem Fragment verschieben statt klonen
const tpl = document.createElement('template');
tpl.innerHTML = '<p>Einmalig</p>';
document.body.append(tpl.content); // verschiebt die Knoten
console.log(tpl.content.childNodes.length); // Vorlage ist jetzt leer
// Wichtig · Fallstricke
- Vor dem Einfügen klonen: Wenn du
template.contentdirekt perappend()oderappendChild()einfügst, werden die Knoten verschoben. Danach ist die Vorlage leer. Klone deshalb immer mitcloneNode(true)oderdocument.importNode(). - Fragment nach dem Einfügen leer: Nach
append(clone)ist auch der Klon (einDocumentFragment) leer. Hol dir Referenzen auf die Elemente deshalb vor dem Einfügen, z. B. mitclone.firstElementChild. - Skripte:
<script>-Elemente aus einem Template laufen nach dem Klonen und Einfügen trotzdem nicht, wenn die Vorlage perinnerHTMLgeparst wurde. Sie sind dann als „already started“ markiert. Für ausführbare Skripte musst du neue Elemente mitdocument.createElement('script')erzeugen. - Custom Elements: Custom Elements in
contentwerden erst aufgewertet (upgrade), wenn sie ins aktive Dokument übernommen werden.document.importNode()sorgt dafür, dass das früher geschieht. - Sicherheit: Befülle Templates mit
textContentstattinnerHTML, damit Nutzerdaten keine XSS-Lücken öffnen. - Kompatibilität: Wird von allen modernen Browsern unterstützt, der Internet Explorer kennt die Eigenschaft nicht. Deklaratives Shadow DOM (
<template shadowrootmode>) ist ein eigenes, neueres Feature.