<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.

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

Attribute

Dieses Element umfasst die globalen Attribute.

shadowrootmode

Erstellt einen Shadow Root für das übergeordnete Element. Es ist eine deklarative Version der Methode Element.attachShadow() und akzeptiert die gleichen Aufzählungswerte.

open

Ermöglicht den Zugang zum internen Shadow Root DOM für JavaScript (empfohlen für die meisten Anwendungsfälle).

closed

Verbirgt das interne 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. Wenn das Attribut nicht gesetzt ist, auf einen nicht erlaubten Wert gesetzt ist oder wenn bereits ein ShadowRoot im selben übergeordneten Element deklarativ erstellt wurde, wird ein HTMLTemplateElement konstruiert. Ein HTMLTemplateElement kann nicht nachträglich in ein Shadow Root umgewandelt werden, z. B. durch Setzen von HTMLTemplateElement.shadowRootMode.

Hinweis: Sie könnten das nicht standardisierte Attribut shadowroot in älteren Tutorials und Beispielen finden, die in Chrome 90-110 unterstützt wurden. Dieses Attribut wurde inzwischen entfernt und durch das standardisierte Attribut shadowrootmode ersetzt.

shadowrootclonable

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

shadowrootdelegatesfocus

Setzt den Wert der delegatesFocus-Eigenschaft eines ShadowRoot, das mit diesem Element erstellt wurde, 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 Standardwert ist false.

shadowrootserializable Experimentell

Setzt den Wert der serializable-Eigenschaft eines ShadowRoot, das mit diesem Element erstellt wurde, auf true. Wenn gesetzt, kann der Shadow Root durch Aufrufen der Methoden Element.getHTML() oder ShadowRoot.getHTML() mit dem Parameter options.serializableShadowRoots auf true serialisiert werden. Der Standardwert ist false.

Nutzungshinweise

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 Standard-content-Eigenschaft (ohne ein entsprechendes Inhalts-/Markup-Attribut). Diese content-Eigenschaft ist schreibgeschützt und hält ein DocumentFragment, das den durch das Template dargestellten DOM-Teilbaum enthält. Dieses Fragment kann über die Methode cloneNode geklont und in das DOM eingefügt werden.

Seien Sie vorsichtig beim Verwenden der content-Eigenschaft, da das zurückgegebene DocumentFragment ein unerwartetes Verhalten zeigen kann. Für weitere Details lesen Sie den Abschnitt Vermeidung von DocumentFragment-Fallstricken unten.

Deklaratives Shadow DOM

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

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

Beispiele

Generieren 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. Dann folgt das Template, das die Struktur eines HTML-Fragments beschreibt, das eine einzelne Tabellenzeile darstellt.

Nachdem die Tabelle erstellt und das Template definiert wurden, verwenden wir JavaScript, um Zeilen in die Tabelle einzufügen, wobei jede Zeile auf Basis des Templates 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 originale HTML-Tabelle, mit zwei neuen Zeilen, die über JavaScript hinzugefügt wurden:

Implementieren eines deklarativen Shadow DOM

In diesem Beispiel wird eine versteckte Support-Warnung zu Beginn des Markups eingefügt. Diese Warnung wird später via JavaScript angezeigt, falls der Browser das Attribut shadowrootmode 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 auf das Shadow Root beschränkt, das an der Stelle 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 ein deklarativ erstelltes 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 Attribut shadowrootmode. Dies zeigt sowohl ein nicht fokussierbares <div> mit Text als auch ein fokussierbares <input>-Element an. Es verwendet auch CSS, um Elemente mit :focus blau zu färben, und um das normale Styling des Host-Elements einzustellen.

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, nur dass er das Attribut shadowrootdelegatesfocus setzt, das den Fokus an das erste fokussierbare Element im Tree delegiert, wenn ein nicht fokussierbares Element im Tree 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 einen gelb-grünen Rand um das übergeordnete <div>-Element zu legen, wenn es den Fokus hat.

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

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

Screenshot of code with no focus set

Für das Shadow Root mit gesetztem shadowrootdelegatesfocus führt ein Klick auf den Text (der nicht fokussierbar ist) zur Auswahl des <input>-Elements, da dies das erste fokussierbare Element im Tree ist. Dies fokussiert auch das übergeordnete Element, wie unten gezeigt.

Screenshot of the code where the element has focus

Vermeidung von DocumentFragment-Fallstricken

Wenn ein DocumentFragment-Wert übergeben wird, verschieben Node.appendChild und ähnliche Methoden nur die Kindknoten dieses Wertes in den Zielknoten. Daher ist es normalerweise vorzuziehen, Ereignishandler an den Kindern eines DocumentFragment anzuhängen, anstatt 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);

Resultat

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, da ein Ereignishandler zum ersten Kindknoten von secondClone hinzugefügt wird, der Ereignishandler beim Aufruf von appendChild kopiert, und ein Klick darauf funktioniert wie erwartet.

Technische Zusammenfassung

Inhaltskategorien Metadata Content, Flow Content, Phrasing Content, script-supporting element
Erlaubte Inhalte Keine Einschränkungen
Tag-Auslassung Keine, sowohl das Start- als auch das End-Tag sind obligatorisch.
Erlaubte Eltern Jedes Element, das Metadata Content, Phrasing Content akzeptiert, oder Script-supporting elements. Ebenfalls erlaubt als Kind eines <colgroup> Elements, das keine span Attribut hat.
Implizite ARIA-Rolle Keine entsprechende Rolle
Erlaubte ARIA-Rollen Keine role erlaubt
DOM Interface [`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