<template>

Zuletzt aktualisiert am 6. Februar 2026

Das <template>-Element definiert wiederverwendbare HTML-Vorlagen, die beim Laden der Seite nicht gerendert werden. Der Inhalt eines Templates ist komplett inert: Kein CSS wird angewendet, keine Scripts werden ausgeführt, keine Bilder werden geladen. Erst wenn du per JavaScript mit content.cloneNode(true) eine Kopie erstellst und diese ins DOM einfügst, wird der Inhalt sichtbar und aktiv. Das macht <template> zu einem wichtigen Baustein für Web Components und dynamische UIs.

Grundlagen

Das <template>-Element ist ein besonderer Container, dessen Inhalt vom Browser zwar geparst, aber nicht gerendert wird. Das ist ein entscheidender Unterschied zu einem Element mit display: none, denn ein verstecktes <div> wird trotzdem vollständig verarbeitet: Bilder werden geladen, Scripts ausgeführt, CSS berechnet. Bei <template> passiert nichts davon.

  • Der Inhalt eines Templates wird vom HTML-Parser validiert, aber nicht ausgeführt: keine Script-Ausführung, kein Bild-Download, kein CSS-Rendering
  • Die Eigenschaft content gibt ein DocumentFragment zurück, ein leichtgewichtiges DOM-Objekt, das den Template-Inhalt enthält
  • Mit content.cloneNode(true) erstellst du eine tiefe Kopie des Template-Inhalts, die du ins DOM einfügen kannst
  • Du kannst ein Template beliebig oft klonen, jede Kopie ist unabhängig
  • Templates sind die Grundlage für Web Components: In Kombination mit customElements.define() und Shadow DOM lassen sich eigene HTML-Elemente mit gekapseltem Markup erstellen
  • Ein Template kann jedes gültige HTML enthalten: Elemente, Text, sogar <style>- und <script>-Tags (die erst nach dem Einfügen aktiv werden)
  • Templates haben keine visuellen Attribute, sie sind rein strukturelle Container

Syntax

Grundsyntax
<template id="gruss-template">
  <div class="gruss">Hallo Welt!</div>
</template>

<button id="add-btn">Element hinzufügen</button>
<div id="container"></div>

<script>
  const button = document.getElementById("add-btn");
  const template = document.getElementById("gruss-template");
  const container = document.getElementById("container");

  button.addEventListener("click", () => {
    // Tiefe Kopie des Template-Inhalts erstellen
    const clone = template.content.cloneNode(true);
    // Kopie ins DOM einfügen
    container.appendChild(clone);
  });
</script>
Vorschau

Der entscheidende Ablauf: template.content liefert ein DocumentFragment, cloneNode(true) erstellt eine tiefe Kopie davon, und appendChild() fügt die Kopie ins sichtbare DOM ein. Jeder Klick erzeugt eine neue, unabhängige Kopie.

Beispiele

Liste dynamisch erweitern

Ein häufiger Anwendungsfall: Du hast eine Liste und willst per Klick neue Einträge hinzufügen. Das Template definiert die Struktur eines einzelnen Listenelements, und JavaScript klont es bei Bedarf.

Liste dynamisch erweitern
<template id="item-template">
  <li class="list-item">Neuer Eintrag</li>
</template>

<input id="item-input" type="text"
       placeholder="Neuen Eintrag eingeben..." />
<button id="add-item-btn">Hinzufügen</button>
<ul id="item-list"></ul>

<script>
  const input = document.getElementById("item-input");
  const button = document.getElementById("add-item-btn");
  const template = document.getElementById("item-template");
  const list = document.getElementById("item-list");

  button.addEventListener("click", () => {
    const text = input.value.trim();
    if (!text) return;

    const clone = template.content.cloneNode(true);
    clone.querySelector("li").textContent = text;
    list.appendChild(clone);

    input.value = "";
    input.focus();
  });
</script>
Vorschau

Das Template liefert die Grundstruktur, und per textContent wird der Text vor dem Einfügen angepasst. So trennst du Markup-Struktur sauber von den dynamischen Daten.

Karten aus Daten generieren

Wenn du eine Liste von Objekten hast (z.B. aus einer API), kannst du mit einem Template für jedes Objekt eine Karte erzeugen. Das ist das klassische Muster: Ein Template als Stempel, Daten als Input.

Karten aus Daten generieren
<template id="card-template">
  <div class="card">
    <h3 class="card-title"></h3>
    <p class="card-desc"></p>
  </div>
</template>

<div id="card-container"></div>

<script>
  const kurse = [
    {
      title: "HTML Grundlagen",
      desc: "Lerne die Basis jeder Webseite."
    },
    {
      title: "CSS Layouts",
      desc: "Flexbox und Grid meistern."
    },
    {
      title: "JavaScript Einstieg",
      desc: "Mach deine Webseite interaktiv."
    }
  ];

  const template = document.getElementById("card-template");
  const container = document.getElementById("card-container");

  kurse.forEach((kurs) => {
    const clone = template.content.cloneNode(true);
    clone.querySelector(".card-title")
      .textContent = kurs.title;
    clone.querySelector(".card-desc")
      .textContent = kurs.desc;
    container.appendChild(clone);
  });
</script>
Vorschau

Das Muster ist immer gleich: Template klonen, Daten einsetzen, ins DOM einfügen. Dieses Prinzip skaliert beliebig, ob drei Karten oder dreihundert.

Template in Web Components

Das <template>-Element entfaltet sein volles Potenzial in Kombination mit Web Components. Du definierst ein eigenes HTML-Element mit gekapseltem Markup und Styling. Das Template liefert die Struktur, Shadow DOM sorgt für CSS-Isolation.

<template id="user-card-template">
  <style>
    :host {
      display: block;
      border: 2px solid #e5e7eb;
      border-radius: 12px;
      padding: 16px;
      font-family: sans-serif;
    }
    .name {
      font-size: 1.2em;
      font-weight: bold;
      color: #4338ca;
      margin-bottom: 4px;
    }
    .role {
      color: #666;
      font-size: 0.9em;
    }
  </style>
  <div class="name">
    <slot name="name">Unbekannt</slot>
  </div>
  <div class="role">
    <slot name="role">Keine Rolle</slot>
  </div>
</template>

<script>
  class UserCard extends HTMLElement {
    constructor() {
      super();
      const template =
        document.getElementById("user-card-template");
      const shadow =
        this.attachShadow({ mode: "open" });
      shadow.appendChild(
        template.content.cloneNode(true)
      );
    }
  }

  customElements.define("user-card", UserCard);
</script>

<!-- Verwendung -->
<user-card>
  <span slot="name">Mario</span>
  <span slot="role">Webentwickler</span>
</user-card>

Hier passiert viel auf einmal: Das Template definiert die innere Struktur des Custom Elements inklusive gekapseltem CSS (:host styled das Element selbst). <slot>-Elemente markieren Stellen, an denen der Nutzer des Custom Elements eigenen Inhalt einsetzen kann. Das CSS im Template leakt nicht nach außen, und das CSS der Seite dringt nicht hinein: vollständige Isolation.

Barrierefreiheit

Der Inhalt eines <template>-Elements ist unsichtbar und unerreichbar für Screenreader, und das ist gewollt. Ein Template ist eine Vorlage, kein sichtbarer Inhalt. Erst nachdem du einen Klon per JavaScript ins DOM eingefügt hast, wird der Inhalt für assistive Technologien zugänglich.

Das bedeutet in der Praxis:

  • Der Template-Inhalt selbst braucht keine ARIA-Attribute, er ist nicht Teil des Accessibility Trees
  • Achte darauf, dass die geklonten Elemente barrierefrei sind: Semantische HTML-Elemente, aussagekräftige Texte und korrekte Überschriften-Hierarchien
  • Wenn du Inhalte dynamisch per Template einfügst, können Screenreader-Nutzer das nicht automatisch mitbekommen. Verwende bei Bedarf aria-live="polite" auf dem Container, in den du die Klone einfügst. Damit kündigt der Screenreader neue Inhalte an
  • Bei Web Components mit Shadow DOM: <slot>-Elemente geben den eingesetzten Inhalt korrekt an den Accessibility Tree weiter

Häufige Fehler

Template per CSS stylen wollen: Ein <template>-Element wird nicht gerendert, egal welche CSS-Regeln du darauf anwendest. Es hat kein visuelles Box-Modell, keine Dimensionen, keine Position. Wenn du den Template-Inhalt vor dem Klonen sehen willst, verwendest du das falsche Element. Templates sind unsichtbare Vorlagen, keine versteckten Container.

innerHTML statt content.cloneNode verwenden: Ein häufiger Anfängerfehler ist container.innerHTML = template.innerHTML. Das funktioniert zwar oberflächlich, aber du verlierst Event-Listener, umgehst den sicheren DocumentFragment-Mechanismus und riskierst XSS-Probleme. Verwende immer template.content.cloneNode(true), das ist der vorgesehene und sichere Weg.

Scripts im Template erwarten, dass sie automatisch laufen: JavaScript in einem <script>-Tag innerhalb eines Templates wird nicht ausgeführt, weder beim Laden der Seite noch beim Klonen und Einfügen ins DOM. Wenn du Script-Logik brauchst, schreibe sie außerhalb des Templates oder füge das Script-Element nach dem Klonen manuell dem DOM hinzu.

Template nur einmal verwenden statt klonen: Wenn du document.getElementById("template").content direkt (ohne cloneNode) an appendChild() übergibst, wird der Inhalt aus dem Template verschoben statt kopiert. Danach ist das Template leer, und du kannst es nicht erneut verwenden. Verwende immer cloneNode(true), um eine Kopie zu erstellen.

Template-Inhalt per JavaScript durchsuchen, bevor er im DOM ist: Nach dem Klonen mit cloneNode(true) erhältst du ein DocumentFragment. Du kannst auf diesem Fragment querySelector() verwenden, aber sobald du es per appendChild() einfügst, wird das Fragment geleert. Wenn du Referenzen auf eingefügte Elemente brauchst, hole sie dir nach dem Einfügen aus dem DOM oder vor dem Einfügen aus dem Fragment.

Browser-Kompatibilität

Das template-Element wird von allen modernen Browsern vollständig unterstützt. Es gehört zum HTML5-Standard und ist seit vielen Jahren stabil implementiert.

ClientUnterstützungHinweise
ChromeKomplettVollständige Unterstützung seit Chrome 26.
FirefoxKomplettVollständige Unterstützung seit Firefox 22.
SafariKomplettVollständige Unterstützung seit Safari 8.
EdgeKomplett
OperaKomplett

Email-Kompatibilität

Das template-Element wird von keinem E-Mail-Client unterstützt. E-Mail-Clients erlauben kein JavaScript, und ohne JavaScript kann der Template-Inhalt nicht geklont und eingefügt werden. Der Inhalt bleibt unsichtbar.

ClientUnterstützungHinweise
Apple MailKeineTemplate-Inhalt wird nicht gerendert. Kein JavaScript verfügbar.
GmailKeineEntfernt das template-Element und seinen Inhalt komplett.
OutlookKeineKeine Unterstützung. Template-Inhalt bleibt unsichtbar.
ThunderbirdKeineTemplate-Element wird ignoriert, Inhalt nicht angezeigt.
Yahoo MailKeineEntfernt template-Elemente und JavaScript.

Verwandte Elemente

Bleib auf dem Laufenden

Erhalte neue Inhalte direkt in dein Postfach

Mit der Anmeldung akzeptierst du unsere Datenschutzerklärung. Du kannst dich jederzeit über den Link in den E-Mails wieder abmelden.

Was erwartet dich?

Neue Artikel & Videos

Wenn ich was Neues veröffentliche, erfährst du's hier zuerst.

Plattform & Kurs-Updates

Neue Kurse, Referenz-Updates und gelegentlich Sonderpreise zum Launch.

Einmal die Woche in deinem Postfach

Kurz, auf den Punkt, kein Spam.