<template>: Das Content Template-Element

Baseline Widely available *

This feature is well established and works across many devices and browser versions. It’s been available across browsers since November 2015.

* Some parts of this feature may have varying levels of support.

Das <template> HTML-Element dient als Mechanismus zum Halten von HTML-Fragmenten, die entweder später über JavaScript verwendet oder sofort in den Shadow DOM generiert werden können.

Attribute

Dieses Element umfasst die globalen Attribute.

shadowrootmode

Erstellt einen Shadow Root für das Elternelement. Es ist eine deklarative Version der Methode Element.attachShadow() und akzeptiert die gleichen enumerierten Werte.

open

Macht den internen Shadow Root DOM für JavaScript zugänglich (empfohlen für die meisten Anwendungsfälle).

closed

Verbirgt den internen Shadow Root DOM vor JavaScript.

Hinweis: Der HTML-Parser erstellt ein ShadowRoot-Objekt im DOM für das erste <template> in einem Knoten mit diesem Attribut, das auf einen erlaubten Wert gesetzt ist. Falls das Attribut nicht gesetzt ist, auf einen nicht erlaubten Wert gesetzt ist oder wenn bereits ein ShadowRoot deklarativ im selben Elternelement erstellt wurde, wird ein HTMLTemplateElement konstruiert. Ein HTMLTemplateElement kann nach dem Parsen nicht mehr in einen Shadow Root umgewandelt werden, zum Beispiel durch das Setzen von HTMLTemplateElement.shadowRootMode.

Hinweis: Möglicherweise finden Sie das nicht-standardmäßige shadowroot-Attribut in älteren Tutorials und Beispielen, die früher in Chrome 90-110 unterstützt wurden. Dieses Attribut wurde inzwischen entfernt und durch das standardmäßige shadowrootmode-Attribut ersetzt.

shadowrootclonable

Setzt den Wert der clonable-Eigenschaft eines mit diesem Element erstellten ShadowRoot auf true. Wenn gesetzt, wird ein Klon des Shadow Hosts (das Elternelement dieses <template>), das mit Node.cloneNode() oder Document.importNode() erstellt wurde, einen Shadow Root in der Kopie enthalten.

shadowrootdelegatesfocus

Setzt den Wert der delegatesFocus-Eigenschaft eines mit diesem Element erstellten ShadowRoot auf true. Wenn dies gesetzt ist und ein nicht-fokussierbares Element im Shadow Tree ausgewählt wird, wird der Fokus an das erste fokussierbare Element im Tree delegiert. Der Wert ist standardmäßig false.

shadowrootserializable Experimentell

Setzt den Wert der serializable-Eigenschaft eines mit diesem Element erstellten ShadowRoot auf true. Wenn gesetzt, kann der Shadow Root durch Aufruf der Methoden Element.getHTML() oder ShadowRoot.getHTML() mit dem Parameter options.serializableShadowRoots auf true gesetzt seriell werden. Der Wert ist standardmäßig false.

Verwendungshinweise

Es gibt zwei Hauptmethoden, das <template>-Element zu verwenden.

Template-Dokumentfragment

Standardmäßig wird der Inhalt des Elements nicht gerendert. Das entsprechende HTMLTemplateElement-Interface enthält eine standardmäßige content-Eigenschaft (ohne ein äquivalentes Content-/Markup-Attribut). Diese content-Eigenschaft ist schreibgeschützt und hält ein DocumentFragment, das den durch das Template dargestellten DOM-Subtree enthält. Dieses Fragment kann über die Methode cloneNode geklont und in den DOM eingefügt werden.

Seien Sie vorsichtig bei der Verwendung der content-Eigenschaft, da das zurückgegebene DocumentFragment unerwartetes Verhalten zeigen kann. Für weitere Details siehe den Abschnitt Vermeiden von DocumentFragment-Fallen unten.

Deklarativer Shadow DOM

Wenn das <template>-Element das Attribut shadowrootmode mit einem Wert von entweder open oder closed enthält, erzeugt der HTML-Parser sofort einen Shadow DOM. Das Element wird im DOM durch seinen Inhalt ersetzt, der in einem ShadowRoot eingewickelt und an das Elternelement angehängt wird. Dies ist das deklarative Äquivalent zum Aufruf von Element.attachShadow(), um einen Shadow Root an ein Element anzuhängen.

Wenn das Element einen anderen Wert für shadowrootmode hat oder nicht das Attribut shadowrootmode besitzt, erzeugt der Parser ein HTMLTemplateElement. Ebenso wird, wenn es mehrere deklarative Shadow Roots gibt, nur der erste durch einen ShadowRoot ersetzt — nachfolgende Instanzen werden als HTMLTemplateElement-Objekte geparst.

Beispiele

Erzeugen von Tabellenzeilen

Zuerst beginnen wir mit dem HTML-Teil des Beispiels.

html
<table id="producttable">
  <thead>
    <tr>
      <td>UPC_Code</td>
      <td>Product_Name</td>
    </tr>
  </thead>
  <tbody>
    <!-- existing data could optionally be included here -->
  </tbody>
</table>

<template id="productrow">
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</template>

Zuerst haben wir eine Tabelle, in die wir später Inhalte mit JavaScript-Code einfügen werden. Anschließend kommt das Template, das die Struktur eines HTML-Fragments beschreibt, das eine einzelne Tabellenzeile darstellt.

Nun, da die Tabelle erstellt und das Template definiert ist, verwenden wir JavaScript, um Zeilen in die Tabelle einzufügen, wobei jede Zeile mit dem Template als Basis konstruiert wird.

js
// Test to see if the browser supports the HTML template element by checking
// for the presence of the template element's content attribute.
if ("content" in document.createElement("template")) {
  // Instantiate the table with the existing HTML tbody
  // and the row with the template
  const tbody = document.querySelector("tbody");
  const template = document.querySelector("#productrow");

  // Clone the new row and insert it into the table
  const clone = template.content.cloneNode(true);
  let td = clone.querySelectorAll("td");
  td[0].textContent = "1235646565";
  td[1].textContent = "Stuff";

  tbody.appendChild(clone);

  // Clone the new row and insert it into the table
  const clone2 = template.content.cloneNode(true);
  td = clone2.querySelectorAll("td");
  td[0].textContent = "0384928528";
  td[1].textContent = "Acme Kidney Beans 2";

  tbody.appendChild(clone2);
} else {
  // Find another way to add the rows to the table because
  // the HTML template element is not supported.
}

Das Ergebnis ist die ursprüngliche HTML-Tabelle, der zwei neue Zeilen über JavaScript hinzugefügt wurden:

Implementierung eines deklarativen Shadow DOM

In diesem Beispiel wird eine versteckte Unterstützung-Warnung zu Beginn des Markups eingefügt. Diese Warnung wird später über JavaScript angezeigt, wenn der Browser das shadowrootmode-Attribut nicht unterstützt. Danach gibt es zwei <article>-Elemente, die jeweils verschachtelte <style>-Elemente mit unterschiedlichen Verhaltensweisen enthalten. Das erste <style>-Element ist global für das gesamte Dokument. Das zweite ist dem Shadow Root zugeordnet, der anstelle des <template>-Elements aufgrund des shadowrootmode-Attributs generiert wird.

html
<p hidden>
  ⛔ Your browser doesn't support <code>shadowrootmode</code> attribute yet.
</p>
<article>
  <style>
    p {
      padding: 8px;
      background-color: wheat;
    }
  </style>
  <p>I'm in the DOM.</p>
</article>
<article>
  <template shadowrootmode="open">
    <style>
      p {
        padding: 8px;
        background-color: plum;
      }
    </style>
    <p>I'm in the shadow DOM.</p>
  </template>
</article>
js
const isShadowRootModeSupported =
  HTMLTemplateElement.prototype.hasOwnProperty("shadowRootMode");

document
  .querySelector("p[hidden]")
  .toggleAttribute("hidden", isShadowRootModeSupported);

Deklarativer Shadow DOM mit delegiertem Fokus

Dieses Beispiel zeigt, wie shadowrootdelegatesfocus auf einen deklarativ erstellten Shadow Root angewendet wird und welche Auswirkungen dies auf den Fokus hat.

Der Code deklariert zuerst einen Shadow Root innerhalb eines <div>-Elements, unter Verwendung des <template>-Elements mit dem shadowrootmode-Attribut. Dies zeigt sowohl ein nicht fokussierbares <div> mit Text als auch ein fokussierbares <input>-Element. Es wird auch CSS verwendet, um Elemente mit :focus blau zu gestalten und das normale Styling des Host-Elements zu setzen.

html
<div>
  <template shadowrootmode="open">
    <style>
      :host {
        display: block;
        border: 1px dotted black;
        padding: 10px;
        margin: 10px;
      }
      :focus {
        outline: 2px solid blue;
      }
    </style>
    <div>Clickable Shadow DOM text</div>
    <input type="text" placeholder="Input inside Shadow DOM" />
  </template>
</div>

Der zweite Codeblock ist identisch, außer dass er das Attribut shadowrootdelegatesfocus setzt, das den Fokus auf das erste fokussierbare Element im Baum delegiert, wenn ein nicht fokussierbares Element im Baum ausgewählt wird.

html
<div>
  <template shadowrootmode="open" shadowrootdelegatesfocus>
    <style>
      :host {
        display: block;
        border: 1px dotted black;
        padding: 10px;
        margin: 10px;
      }
      :focus {
        outline: 2px solid blue;
      }
    </style>
    <div>Clickable Shadow DOM text</div>
    <input type="text" placeholder="Input inside Shadow DOM" />
  </template>
</div>

Zuletzt verwenden wir das folgende CSS, um dem Elternelement <div> einen roten Rahmen zu geben, wenn es fokussiert ist.

css
div:focus {
  border: 2px solid red;
}

Die Ergebnisse werden unten gezeigt. Wenn das HTML zuerst gerendert wird, haben die Elemente keine Formatierung, wie im ersten Bild gezeigt. Für den Shadow Root, der nicht shadowrootdelegatesfocus gesetzt hat, können Sie überall außer dem <input> anklicken, und der Fokus ändert sich nicht (wenn Sie das <input>-Element auswählen, sieht es wie das zweite Bild aus).

Screenshot des Codes ohne gesetzten Fokus

Für den Shadow Root mit gesetztem shadowrootdelegatesfocus, wird durch Klicken auf den Text (der nicht fokussierbar ist) das <input>-Element ausgewählt, da dies das erste fokussierbare Element im Baum ist. Dies fokussiert auch das Elternelement, wie unten gezeigt.

Screenshot des Codes, bei dem das Element den Fokus hat

Vermeiden von DocumentFragment-Fallen

Wenn ein DocumentFragment-Wert übergeben wird, verschieben Node.appendChild und ähnliche Methoden nur die Kindknoten dieses Wertes in den Zielknoten. Daher ist es in der Regel vorzuziehen, Ereignishandler an die Kinder eines DocumentFragment anzuhängen, statt an das DocumentFragment selbst.

Betrachten Sie das folgende HTML und JavaScript:

HTML

html
<div id="container"></div>

<template id="template">
  <div>Click me</div>
</template>

JavaScript

js
const container = document.getElementById("container");
const template = document.getElementById("template");

function clickHandler(event) {
  event.target.append(" — Clicked this div");
}

const firstClone = template.content.cloneNode(true);
firstClone.addEventListener("click", clickHandler);
container.appendChild(firstClone);

const secondClone = template.content.cloneNode(true);
secondClone.children[0].addEventListener("click", clickHandler);
container.appendChild(secondClone);

Ergebnis

Da firstClone ein DocumentFragment ist, werden beim Aufruf von appendChild nur seine Kinder zu container hinzugefügt; die Ereignishandler von firstClone werden nicht kopiert. Im Gegensatz dazu wird, weil ein Ereignishandler zum ersten Kindknoten von secondClone hinzugefügt wird, der Ereignishandler kopiert, wenn appendChild aufgerufen wird, und ein Klick darauf funktioniert wie erwartet.

Technische Zusammenfassung

Content-Kategorien Metadaten-Inhalt, Flussinhalt, Phraseninhalt, skriptunterstützender Inhalt
Erlaubter Inhalt Keine Einschränkungen
Tag-Auslassung Keine, sowohl der Start- als auch der End-Tag sind obligatorisch.
Erlaubte Eltern Jedes Element, das Metadaten-Inhalt, Phraseninhalt oder skriptunterstützenden Inhalt akzeptiert. Auch erlaubt als Kind eines <colgroup> Elements, das nicht das span-Attribut hat.
Implizite ARIA-Rolle Keine entsprechende Rolle
Erlaubte ARIA-Rollen Keine role erlaubt
DOM-Schnittstelle [`HTMLTemplateElement`](/de/docs/Web/API/HTMLTemplateElement)

Spezifikationen

Specification
HTML Standard
# the-template-element

Browser-Kompatibilität

BCD tables only load in the browser

Siehe auch