<template> : l'élément de modèle de contenu
Baseline
Widely available
*
Cette fonctionnalité est bien établie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis novembre 2015.
* Certaines parties de cette fonctionnalité peuvent bénéficier de prise en charge variables.
L'élément HTML <template> sert de mécanisme pour contenir des fragments HTML, qui peuvent être utilisés plus tard via JavaScript ou générés immédiatement dans le DOM d'ombre.
Attributs
Cet élément inclut les attributs universels.
shadowrootmode-
Crée une racine d'ombre pour l'élément parent. Il s'agit d'une version déclarative de la méthode
Element.attachShadow()et accepte les mêmes valeurs énumérées.open-
Expose le DOM interne de la racine d'ombre pour JavaScript (recommandé pour la plupart des cas d'usage).
closed-
Masque le DOM interne de la racine d'ombre pour JavaScript.
Note : L'analyseur HTML crée un objet
ShadowRootdans le DOM pour le premier<template>d'un nœud dont cet attribut est défini sur une valeur autorisée. Si l'attribut n'est pas défini, ou n'est pas défini sur une valeur autorisée — ou si uneShadowRoota déjà été créée de manière déclarative dans le même parent — alors unHTMLTemplateElementest construit. UnHTMLTemplateElementne peut pas être transformé en racine d'ombre après l'analyse, par exemple, en définissantHTMLTemplateElement.shadowRootMode.Note : Vous pouvez rencontrer l'attribut non standard
shadowrootdans d'anciens tutoriels et exemples qui étaient pris en charge dans Chrome 90-110. Cet attribut a depuis été supprimé et remplacé par l'attribut standardshadowrootmode. shadowrootclonable-
Définit la valeur de la propriété
clonabled'un objetShadowRootcréé avec cet élément àtrue. Si défini, un clone de l'hôte d'ombre (l'élément parent de ce<template>) créé avecNode.cloneNode()ouDocument.importNode()inclura une racine d'ombre dans la copie. shadowrootdelegatesfocus-
Définit la valeur de la propriété
ShadowRoot.delegatesFocusd'un objetShadowRootcréé avec cet élément àtrue. Si cela est défini et qu'un élément non sélectionnable dans l'arbre d'ombre est sélectionné, la sélection est déléguée au premier élément sélectionnable de l'arbre. La valeur par défaut estfalse. shadowrootreferencetargetExpérimental-
Définit la valeur de la propriété
referenceTargetd'un objetShadowRootcréé avec cet élément. La valeur doit être l'identifiant d'un élément à l'intérieur du DOM d'ombre. Si défini, les références ciblant l'élément hôte depuis l'extérieur du DOM d'ombre feront que l'élément cible référencé deviendra la cible effective de la référence à l'élément hôte. shadowrootserializable-
Définit la valeur de la propriété
ShadowRoot.serializabled'un objetShadowRootcréé avec cet élément àtrue. Si défini, la racine d'ombre peut être sérialisée en appelant les méthodesElement.getHTML()ouShadowRoot.getHTML()avec le paramètreoptions.serializableShadowRootsdéfini àtrue. La valeur par défaut estfalse.
Notes d'utilisation
Cet élément n'a pas de contenu autorisé, car tout ce qui est imbriqué à l'intérieur dans le code source HTML ne devient pas réellement enfant de l'élément <template>. La propriété Node.childNodes de l'élément <template> est toujours vide, et vous ne pouvez accéder à ce contenu imbriqué que via la propriété spéciale content. Cependant, si vous appelez Node.appendChild() ou des méthodes similaires sur l'élément <template>, vous insérerez des enfants dans l'élément <template> lui-même, ce qui viole son modèle de contenu et ne met pas à jour le DocumentFragment retourné par la propriété content.
En raison de la façon dont l'élément <template> est analysé, toutes les balises <html>, <head> et <body> ouvrantes et fermantes à l'intérieur du template sont des erreurs de syntaxe et sont ignorées par l'analyseur, donc <template><head><title>Test</title></head></template> équivaut à <template><title>Test</title></template>.
Il existe deux principales façons d'utiliser l'élément <template>.
Fragment de document de template
Par défaut, le contenu de l'élément n'est pas affiché.
L'interface HTMLTemplateElement correspondante inclut une propriété standard content (sans attribut de contenu/marquage équivalent). Cette propriété content est en lecture seule et contient un DocumentFragment qui inclut le sous-arbre DOM représenté par le template.
Les méthodes Node.cloneNode() et Document.importNode() créent toutes deux une copie d'un nœud. La différence est que importNode() clone le nœud dans le contexte du document appelant, tandis que cloneNode() utilise le document du nœud cloné. Le contexte du document détermine le CustomElementRegistry pour la construction de tout élément personnalisé. Pour cette raison, utilisez document.importNode() pour cloner le fragment content afin que les descendants d'éléments personnalisés soient construits selon les définitions du document courant, plutôt que du document séparé qui possède le contenu du template. Voir les exemples de la page Node.cloneNode() pour plus de détails.
Notez que le conteneur DocumentFragment lui-même ne doit pas contenir de données. Voir l'exemple Les données sur le DocumentFragment ne sont pas clonées pour plus de détails.
DOM d'ombre déclaratif
Si l'élément <template> contient l'attribut shadowrootmode avec la valeur open ou closed, l'analyseur HTML génère immédiatement un DOM d'ombre. L'élément est remplacé dans le DOM par son contenu enveloppé dans un ShadowRoot, qui est attaché à l'élément parent.
C'est l'équivalent déclaratif de l'appel à Element.attachShadow() pour attacher une racine d'ombre à un élément.
Si l'élément a une autre valeur pour shadowrootmode, ou n'a pas l'attribut shadowrootmode, l'analyseur génère un HTMLTemplateElement.
De même, s'il y a plusieurs racines d'ombre déclaratives, seule la première est remplacée par un ShadowRoot — les suivantes sont analysées comme des objets HTMLTemplateElement.
Exemples
>Générer des lignes de tableau
Nous commençons d'abord par la partie HTML de l'exemple.
<table id="producttable">
<thead>
<tr>
<td>UPC_Code</td>
<td>Product_Name</td>
</tr>
</thead>
<tbody>
<!-- des données existantes pourraient éventuellement être incluses
ici -->
</tbody>
</table>
<template id="productrow">
<tr>
<td class="record"></td>
<td></td>
</tr>
</template>
Au début, on a un tableau HTML pour lequel on insèrera du contenu plus tard grâce à l'aide d'un script JavaScript. Ensuite, on a le template qui décrit la structure du fragment HTML représentant une ligne de tableau.
Avec le tableau créé et le template défini, on utilise JavaScript pour insérer des lignes dans le tableau dont chacune est construite à partir du template.
// On vérifie si le navigateur prend en charge
// l'élément HTML template en vérifiant la présence
// de l'attribut content pour l'élément template.
if ("content" in document.createElement("template")) {
// On prépare une ligne pour le tableau
const tbody = document.querySelector("tbody");
const template = document.querySelector("#productrow");
// On clone la ligne et on l'insère dans le tableau
const clone = document.importNode(template.content, true);
let td = clone.querySelectorAll("td");
td[0].textContent = "1235646565";
td[1].textContent = "Pistolet à portails";
tbody.appendChild(clone);
// On fait de même pour une autre ligne
const clone2 = document.importNode(template.content, true);
td = clone2.querySelectorAll("td");
td[0].textContent = "0384928528";
td[1].textContent = "Compagnon cube";
tbody.appendChild(clone2);
} else {
// Une autre méthode pour ajouter les lignes
// car l'élément HTML n'est pas pris en charge.
}
Le résultat correspond au tableau HTML original avec deux lignes supplémentaires qui ont été ajoutées grâce au code JavaScript :
Implémentation d'un DOM d'ombre déclaratif
Dans cet exemple, un avertissement de compatibilité caché est inclus au début du balisage. Cet avertissement est ensuite affiché via JavaScript si le navigateur ne prend pas en charge l'attribut shadowrootmode. Ensuite, il y a deux éléments <article>, chacun contenant des éléments <style> imbriqués avec des comportements différents. Le premier élément <style> est global à tout le document. Le second est limité à la racine d'ombre générée à la place de l'élément <template> grâce à la présence de l'attribut shadowrootmode.
<p hidden>
⛔ Votre navigateur ne prend pas encore en charge l'attribut
<code>shadowrootmode</code>.
</p>
<article>
<style>
p {
padding: 8px;
background-color: wheat;
}
</style>
<p>Je suis dans le DOM.</p>
</article>
<article>
<template shadowrootmode="open">
<style>
p {
padding: 8px;
background-color: plum;
}
</style>
<p>Je suis dans le DOM d'ombre.</p>
</template>
</article>
const isShadowRootModeSupported = Object.hasOwn(
HTMLTemplateElement.prototype,
"shadowRootMode",
);
document
.querySelector("p[hidden]")
.toggleAttribute("hidden", isShadowRootModeSupported);
DOM d'ombre déclaratif avec délégation de sélection
Cet exemple montre comment shadowrootdelegatesfocus est appliqué à une racine d'ombre créée de manière déclarative, et l'effet que cela a sur la sélection.
Le code commence par déclarer une racine d'ombre à l'intérieur d'un élément <div>, en utilisant l'élément <template> avec l'attribut shadowrootmode.
Cela affiche à la fois un <div> non sélectionnable contenant du texte et un élément <input> sélectionnable.
Il utilise également du CSS pour mettre en forme les éléments avec :focus en bleu, et pour définir la mise en forme normale de l'élément hôte.
<div>
<template shadowrootmode="open">
<style>
:host {
display: block;
border: 1px dotted black;
padding: 10px;
margin: 10px;
}
:focus {
outline: 2px solid blue;
}
</style>
<div>Texte cliquable dans le DOM d'ombre</div>
<input type="text" placeholder="Entrée dans le DOM d'ombre" />
</template>
</div>
Le second bloc de code est identique, à ceci près qu'il définit l'attribut shadowrootdelegatesfocus, qui délègue la sélection au premier élément sélectionnable de l'arbre si un élément non sélectionnable est sélectionné.
<div>
<template shadowrootmode="open" shadowrootdelegatesfocus>
<style>
:host {
display: block;
border: 1px dotted black;
padding: 10px;
margin: 10px;
}
:focus {
outline: 2px solid blue;
}
</style>
<div>Texte cliquable dans le DOM d'ombre</div>
<input type="text" placeholder="Entrée dans le DOM d'ombre" />
</template>
</div>
Enfin, on utilise le CSS suivant pour appliquer une bordure rouge à l'élément parent <div> lorsqu'il est sélectionné.
div:focus {
border: 2px solid red;
}
Les résultats sont affichés ci-dessous.
Lorsque le HTML est d'abord rendu, les éléments n'ont aucune mise en forme, comme le montre la première image.
Pour la racine d'ombre qui n'a pas l'attribut shadowrootdelegatesfocus défini, vous pouvez cliquer n'importe où sauf sur l'élément <input> et la sélection ne change pas (si vous sélectionnez l'élément <input>, il ressemblera à la seconde image).

Pour la racine d'ombre avec l'attribut shadowrootdelegatesfocus défini, cliquer sur le texte (qui n'est pas sélectionnable) sélectionne l'élément <input>, car c'est le premier élément sélectionnable de l'arbre.
Cela sélectionne également l'élément parent comme illustré ci-dessous.

Les données sur le DocumentFragment ne sont pas clonées
Lorsqu'une valeur DocumentFragment est transmise, Node.appendChild et des méthodes similaires déplacent uniquement les nœuds enfants de cette valeur dans le nœud cible. Il est donc généralement préférable d'attacher les gestionnaires d'évènements aux enfants d'un DocumentFragment, plutôt qu'au DocumentFragment lui-même.
Considérez l'exemple HTML et JavaScript suivant :
HTML
<div id="container"></div>
<template id="template">
<div>Cliquez sur moi</div>
</template>
JavaScript
const container = document.getElementById("container");
const template = document.getElementById("template");
function clickHandler(event) {
event.target.append(" — Div cliqué");
}
const firstClone = document.importNode(template.content, true);
firstClone.addEventListener("click", clickHandler);
container.appendChild(firstClone);
const secondClone = document.importNode(template.content, true);
secondClone.children[0].addEventListener("click", clickHandler);
container.appendChild(secondClone);
Résultat
Comme firstClone est un DocumentFragment, seuls ses enfants sont ajoutés à container lorsque appendChild est appelé ; les gestionnaires d'évènements de firstClone ne sont pas copiés. En revanche, comme un gestionnaire d'évènements est ajouté au premier nœud enfant de secondClone, le gestionnaire est copié lors de l'appel à appendChild, et le clic fonctionne comme attendu.
Résumé technique
| Catégories de contenu | Contenu de méta-données, contenu de flux, contenu phrasé, élément destiné aux scripts. |
|---|---|
| Contenu autorisé | Aucune (voir les Notes d'utilisation). |
| Omission de balises | Aucune, la balise d'ouverture et la balise de fermeture sont obligatoires. |
| Parents autorisés |
Tout élément qui accepte du
Contenu de méta-données, du
contenu phrasé, ou
des éléments destinés aux scripts. L'élément <colgroup> est également autorisé
s'il n'a pas l'attribut
span.
|
| Rôle ARIA implicite | Pas de rôle correspondant (angl.) |
| Rôles ARIA autorisés | Aucun role autorisé |
| Interface DOM | HTMLTemplateElement |
Spécifications
| Specification |
|---|
| HTML> # the-template-element> |
Compatibilité des navigateurs
Voir aussi
- Les attributs HTML
partetexportparts - L'élément HTML
<slot> - Les pseudo-classes CSS
:has-slotted,:host,:host()et:host-context() - Les pseudo-éléments CSS
::partet::slotted - L'interface API
ShadowRoot - Utilisation des modèles et des emplacements
- Le module de délimitation de CSS
- DOM d'ombre déclaratif (avec html) dans Utiliser le DOM d'ombre
- DOM d'ombre déclaratif (angl.) sur web.dev (2023)