<template> en HTML : un contenu inerte tant qu'il n'est pas cloné

La balise <template> contient un fragment HTML inerte, jamais affiché ni exécuté tant qu'il n'a pas été cloné en JavaScript pour être inséré ailleurs.
4 min de lecture
Believemy logo

Une liste de messages doit ajouter une nouvelle carte à chaque message reçu, toutes identiques dans leur structure, seul le contenu changeant. Construire cette structure entièrement en JavaScript, avec des appels répétés à createElement, fonctionne mais devient vite difficile à lire et à maintenir dès que la carte contient plusieurs niveaux imbriqués. Il serait plus simple d'écrire le gabarit une fois en HTML, puis de le dupliquer autant de fois que nécessaire.

C'est exactement le rôle de la balise <template> : contenir un fragment de HTML prêt à être cloné, sans jamais être rendu tel quel.


Définition

<template> déclare un fragment de contenu HTML inerte. Le navigateur analyse ce contenu pour vérifier qu'il est syntaxiquement valide, mais ne l'affiche jamais, n'exécute aucun script qu'il contient, ne charge aucune image, et ne le fait jamais participer aux styles ni aux mesures de mise en page de la page. Ce contenu ne devient utilisable qu'après avoir été explicitement cloné en JavaScript.

Cette inertie est la raison d'être de la balise : elle permet d'écrire un gabarit complexe à l'avance, sans effet de bord, prêt à être dupliqué au moment voulu.


Cloner le contenu en JavaScript

La propriété content d'un élément <template> donne accès à un DocumentFragment contenant le gabarit. La méthode cloneNode(true) en produit une copie complète, prête à être insérée dans le document actif.

HTML
<template id="carte-message">
  <article class="message">
    <strong class="auteur"></strong>
    <p class="texte"></p>
  </article>
</template>
HTML
const gabarit = document.getElementById('carte-message');
const clone = gabarit.content.cloneNode(true);
clone.querySelector('.auteur').textContent = 'Camille';
clone.querySelector('.texte').textContent = 'Message bien reçu.';
document.querySelector('.liste').appendChild(clone);

Chaque appel à cloneNode(true) produit une copie indépendante : modifier l'une n'affecte jamais les autres, ni le gabarit d'origine qui reste inchangé dans la balise <template>.


Différence avec un div display none

Un <div style="display:none"> reste un élément parfaitement actif du DOM, simplement invisible à l'écran. Les scripts qu'il contient s'exécutent, ses images se chargent, ses styles sont calculés, et un lecteur d'écran mal configuré peut même parfois l'annoncer. Le contenu d'un <template>, lui, n'est même pas présent dans le DOM actif de la page : il vit dans un document séparé, invisible aux sélecteurs CSS classiques et absent de tout parcours normal du DOM tant qu'il n'a pas été cloné.

Cette distinction se voit aussi dans les outils du navigateur : ouvrir les outils de développement montre le contenu du <div> masqué exactement là où il a été écrit, alors que celui du <template> apparaît replié sous une propriété #document-fragment à part, séparée de l'arbre principal de la page.

Bon à savoir

Cette différence a des conséquences concrètes. Une balise <img> placée dans un <div> masqué télécharge quand même son image en arrière-plan, gaspillant de la bande passante pour un contenu invisible. La même image placée dans un <template> ne déclenche aucun téléchargement tant que le fragment n'a pas été cloné et inséré.


Lien avec <slot>

<slot> prend tout son sens à l'intérieur d'un <template> utilisé pour définir un composant personnalisé : le template décrit la structure interne clonée dans le Shadow DOM, et les emplacements marqués <slot> indiquent où le contenu fourni par l'utilisateur du composant doit s'insérer une fois ce clonage effectué.


Questions fréquentes

QuestionLe contenu d'un template est-il accessible avec querySelector sur le document ?

Non, tant qu'il n'a pas été cloné et inséré dans le document actif. Un appel à document.querySelector('.auteur') ne trouvera rien à l'intérieur d'un <template> non cloné, puisque ce contenu vit dans un document distinct, séparé du DOM principal de la page.

QuestionPeut-on mettre plusieurs éléments racines dans un template ?

Oui, contrairement à beaucoup de frameworks qui exigent un unique élément racine dans un composant, un <template> accepte autant de nœuds frères que nécessaire à son premier niveau, exactement comme n'importe quel autre fragment de HTML.

QuestionFaut-il utiliser template pour du contenu affiché une seule fois au chargement de la page ?

Non, si le contenu doit apparaître une seule fois et rester statique, l'écrire directement dans le HTML de la page reste plus simple et plus rapide. L'intérêt de <template> apparaît quand la même structure doit être dupliquée plusieurs fois, ou clonée en réponse à un événement.

Termes connexes

Découvrez notre glossaire HTML et CSS

Parcourez les termes et définitions les plus couramment utilisés dans le domaine du développement HTML et CSS.

Partager cet article

Tu veux nous aider ? Fais un lien vers cet article sur tes réseaux ou encore mieux : sur ton site, dans un article ou dans ta newsletter.