OUJOOD.COM
Qu'est-ce que l'élément <template> ?
HTML5 API – mise à jour 2026L'élément <template> contient du HTML que le navigateur analyse mais n'affiche pas. Les images ne se téléchargent pas, les scripts ne s'exécutent pas, les styles ne s'appliquent pas — tant que vous ne clonez pas le contenu et ne l'insérez pas dans le DOM vous-même.
Résultat concret : vous écrivez la structure HTML une seule fois, puis vous l'instanciez autant de fois que nécessaire avec des données différentes, sans dupliquer le balisage ni construire tout en JavaScript avec createElement().
Avant cette balise, les développeurs bricolaient avec <script type="text/x-template"> ou des <div> cachés en CSS. L'élément <template> est la réponse native du navigateur à ce besoin — propre, standardisée, et supportée partout depuis des années.
Définir et utiliser un template
Le template se place dans le HTML comme une balise ordinaire. En JavaScript, .content donne accès à son contenu sous forme d'un DocumentFragment. On le clone avec cloneNode(true) — le paramètre true est indispensable pour copier aussi les éléments enfants — puis on insère le clone dans la page.
<!-- Définir le template dans le HTML -->
<template id="modele-carte">
<div class="carte">
<h3 class="carte-titre">Titre par défaut</h3>
<p class="carte-texte">Description par défaut.</p>
</div>
</template>
// Récupérer le template const template = document.getElementById('modele-carte'); // Cloner son contenu — true = clonage profond (tous les enfants) const clone = template.content.cloneNode(true); // Modifier les données du clone avant insertion clone.querySelector('.carte-titre').textContent = 'Shadow DOM'; clone.querySelector('.carte-texte').textContent = 'Isolation du style et du DOM.'; // Insérer le clone dans la page document.body.appendChild(clone);
Chaque appel à cloneNode(true) produit une copie indépendante du template. On peut donc boucler sur un tableau de données et générer autant de cartes que nécessaire à partir du même modèle :
const articles = [
{ titre: 'Custom Elements', texte: 'Créer ses propres balises HTML.' },
{ titre: 'Shadow DOM', texte: 'Encapsuler style et DOM.' },
{ titre: 'Templates', texte: 'Modèles HTML réutilisables.' }
];
const template = document.getElementById('modele-carte');
const conteneur = document.getElementById('liste-articles');
articles.forEach(function(article) {
const clone = template.content.cloneNode(true);
clone.querySelector('.carte-titre').textContent = article.titre;
clone.querySelector('.carte-texte').textContent = article.texte;
conteneur.appendChild(clone);
});
Qu'est-ce que l'élément <slot> ?
Un <slot> est un espace réservé dans un composant. Il dit au navigateur : "ici, place le contenu que l'utilisateur du composant a mis entre mes balises ouvrante et fermante". Le composant garde sa mise en page et son style — seul le contenu change d'une instance à l'autre.
C'est ce qui distingue un composant figé d'un composant vraiment réutilisable. Sans slot, chaque instance affiche exactement la même chose. Avec des slots, chaque instance peut recevoir un titre, une image ou un texte différent.
Slot par défaut
Un <slot> sans attribut name capte tout le contenu de l'élément hôte qui ne cible pas un slot nommé. Si l'utilisateur ne fournit rien, le texte placé entre les balises du slot s'affiche à la place — c'est le contenu de repli.
class CarteSimple extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
div { border: 1px solid #ccc; padding: 1rem; border-radius: 8px; }
</style>
<div>
<slot>Contenu par défaut si rien n'est fourni.</slot>
</div>
`;
}
}
customElements.define('carte-simple', CarteSimple);
Ce que l'on place entre les balises <carte-simple> atterrit automatiquement dans le slot. Sans contenu fourni, le texte de repli du slot s'affiche :
<!-- Le paragraphe sera projeté dans le <slot> --> <carte-simple> <p>Voici mon contenu personnalisé.</p> </carte-simple> <!-- Sans contenu : affiche le texte par défaut du slot --> <carte-simple></carte-simple>
Slots nommés
Quand un composant a plusieurs zones de contenu distinctes — un avatar, un nom, une description — les slots nommés entrent en jeu. Côté composant, on attribue un name à chaque slot. Côté utilisateur, on cible le bon slot avec l'attribut slot="..." sur l'élément à injecter.
class CarteProfil extends HTMLElement {
connectedCallback() {
const shadow = this.attachShadow({ mode: 'open' });
shadow.innerHTML = `
<style>
.carte { border: 1px solid #ddd; border-radius: 8px; padding: 1rem; max-width: 280px; }
.avatar { width: 64px; height: 64px; border-radius: 50%; display: block; margin-bottom: 0.8rem; }
h3 { margin: 0 0 0.3rem; color: #0066cc; }
p { margin: 0; color: #666; font-size: 0.9rem; }
</style>
<div class="carte">
<!-- Slot nommé pour l'avatar -->
<slot name="avatar"></slot>
<!-- Slot nommé pour le nom -->
<slot name="nom">Nom inconnu</slot>
<!-- Slot nommé pour la description -->
<slot name="description"></slot>
</div>
`;
}
}
customElements.define('carte-profil', CarteProfil);
Utilisation avec des slots nommés dans le HTML :
<carte-profil> <img slot="avatar" src="photo.jpg" alt="Avatar Oujood"> <span slot="nom">Oujood</span> <span slot="description">Développeur Web passionné</span> </carte-profil>
Combiner <template> et <slot> dans un Custom Element
La bonne pratique : écrire la structure dans un <template> dans le HTML, puis le cloner dans le Shadow DOM du Custom Element via connectedCallback. La structure reste lisible en HTML, la logique reste dans la classe JavaScript — chaque chose à sa place.
<!-- 1. Définir le template avec des slots dans le HTML -->
<template id="tpl-article">
<style>
article { border-left: 4px solid #0066cc; padding: 0.8rem 1rem; margin-bottom: 1rem; }
h4 { margin: 0 0 0.4rem; color: #0066cc; }
p { margin: 0; color: #444; }
</style>
<article>
<h4><slot name="titre">Sans titre</slot></h4>
<p><slot name="contenu">Sans contenu.</slot></p>
</article>
</template>
// 2. Custom Element qui clone le template dans son Shadow DOM class ArticleWeb extends HTMLElement { connectedCallback() { const template = document.getElementById('tpl-article'); const shadow = this.attachShadow({ mode: 'open' }); // Cloner le template et l'injecter dans le shadow root shadow.appendChild(template.content.cloneNode(true)); } } customElements.define('article-web', ArticleWeb);
<!-- 3. Utilisation dans le HTML -->
<article-web>
<span slot="titre">Custom Elements</span>
<span slot="contenu">Créez vos propres balises HTML natives.</span>
</article-web>
<article-web>
<span slot="titre">Shadow DOM</span>
<span slot="contenu">Encapsulez style et structure de vos composants.</span>
</article-web>
Récapitulatif
<template> stocke du HTML inactif que cloneNode(true) réveille. <slot> ouvre une fenêtre dans le composant pour laisser entrer le contenu extérieur — sans nom pour tout attraper, avec name pour cibler précisément. Ces deux éléments complètent Custom Elements et Shadow DOM : ensemble, ils forment un système de composants HTML natifs, encapsulés et réutilisables, sans aucune dépendance.
Par carabde | Mis à jour le 17 avril 2026