- <template> permite definir contenido inerte que se clona y activa bajo demanda.
- Se accede vía .content y se inserta con importNode/cloneNode para un render controlado.
- Declarative Shadow DOM con shadowrootmode encapsula estilos y estructura sin JS.
- Combina templates con un buen boilerplate HTML5 y metadatos para SEO/social.
Si desarrollas en Frontend, tarde o temprano te toparás con la etiqueta <template> como herramienta clave para componer y reutilizar fragmentos de interfaz sin ensuciar el DOM ni pagar costes de render en el momento. Es el puente entre el HTML de toda la vida y dinámicas modernas donde el contenido se inyecta con JavaScript.
Antes, gran parte de las “plantillas” vivían en el servidor (PHP, Ruby, Python…). Hoy podemos montar estructuras reutilizables en el navegador con motores como Mustache, Handlebars, Nunjucks o incluso lógica propia con Web Components, y el elemento <template> se ha convertido en la base ideal: contenido inerte, listo para clonar cuando toque.
¿Qué es la etiqueta template y por qué es tan útil?
La etiqueta <template> define un fragmento de HTML que el navegador analiza pero no renderiza ni ejecuta hasta que lo activas. Eso significa que puedes dejar preparado un bloque de UI (una fila de una tabla, una tarjeta de usuario, un artículo) y solo “producirlo” cuando lo necesites.
En la práctica, el contenido del template no forma parte del documento activo: no aparece en el árbol renderizado y no afecta al layout, ni dispara cargas de imágenes, ni ejecuta scripts. Todo queda dormido dentro de la propiedad JavaScript template.content hasta que clonas ese contenido y lo insertas.
Características clave de <template>
Para entender bien cómo se comporta, conviene repasar sus rasgos distintivos y cómo afectan al flujo de la página, ya que cada característica está pensada para controlar la ejecución y el render de la UI.
- El contenido se parsea por el navegador, pero no se dibuja; permanece invisible y sin ocupar espacio.
- Es inerte: nada dentro del template se ejecuta o carga (scripts, imágenes, audio o vídeo) hasta que lo activas.
- No pertenece al documento principal: un document.getElementById() o querySelector() sobre document no encuentra sus nodos internos; debes acceder vía template.content.
- Puedes ubicarlo en head, body o frameset, con cualquier HTML válido dentro; su versatilidad permite diseñar plantillas complejas sin penalizar el render inicial.
El soporte de <template> llegó hace tiempo a los navegadores modernos: Chrome, Firefox, Safari, Opera y los navegadores móviles actuales lo manejan sin problema; el gran ausente es Internet Explorer, que nunca implementó la etiqueta. En versiones históricas el soporte llegó progresivamente (Firefox 22+, Chrome 26+, Safari 7.1+, Opera 15+, iOS 8+, Android 4.4+, etc.).
Para comprobar si el entorno soporta bien la API, bastan dos líneas. La técnica estándar consiste en comprobar la existencia de la propiedad «content» en un elemento template recién creado:
if ("content" in document.createElement("template")) {
// Soporte nativo disponible
} else {
// Toca usar un polyfill o estrategia alternativa
}
Aunque en 2025 el caso habitual es tener soporte nativo, en entornos corporativos aún se encuentran navegadores viejos; por eso conviene mantener una detección defensiva para no romper la UI si falta la implementación.
Crear tu primer template con HTML normal
Definir un template es tan sencillo como escribir la estructura HTML que deseas reutilizar y envolverla en <template>. Lo habitual es dotarlo de un id descriptivo para localizarlo después con JavaScript y mantener el contenido lo más limpio y semántico posible.
<template id="plantilla-fila">
<tr>
<td></td>
<td></td>
<td></td>
</tr>
</template>
En este ejemplo, la plantilla describe una fila de tabla con tres celdas vacías que rellenaremos al vuelo. Puedes colocar el template justo después de la tabla o incluso en el head; no afecta al diseño hasta que lo clones e insertes.
Activar un template: importNode, cloneNode y .content
La propiedad content expone un DocumentFragment que contiene todo lo que hay dentro del template. Para activarlo, lo normal es clonar el fragmento y adjuntarlo al DOM. Aquí entra en juego document.importNode() (clonado profundo) o directamente template.content.cloneNode(true), que es conciso y legible.
const t = document.querySelector("#plantilla");
const fragmento = document.importNode(t.content, true);
fragmento.querySelector("h1").textContent = "Hola desde template";
document.body.appendChild(fragmento);
Si prefieres, puedes omitir importNode y clonar el fragmento directamente: const clon = t.content.cloneNode(true). En ambos casos, el resultado es un árbol listo para inyectar, sobre el que podrás ajustar textos, atributos, clases o eventos antes de incorporarlo al documento.
Ejemplo práctico: completar una tabla con filas de un template
Un caso clásico es generar filas de una tabla partiendo de una cabecera fija. Dejas la cabecera estática y guardas en <template> la estructura de la fila. Más tarde, con JavaScript, clonas la fila tantas veces como necesites y la añades al final de la tabla, rellenando cada celda con los datos adecuados.
<table id="data">
<tr>
<th>Nombre</th>
<th>Apellidos</th>
<th>Calificación</th>
</tr>
<template id="user">
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
</template>
</table>
Con la estructura lista, basta con clonar el contenido del template e insertarlo en la tabla. Este patrón funciona igual con datos locales o al recorrer un JSON remoto, porque el nodo resultante es un fragmento estándar del DOM que puedes manipular como cualquier otro elemento.
const table = document.querySelector("#data");
const userTemplate = document.querySelector("#user");
const clonedRow = userTemplate.content.cloneNode(true);
// Aquí podrías ajustar los textos de las celdas según tus datos
// clonedRow.querySelectorAll("td")[0].textContent = "Ada";
// clonedRow.querySelectorAll("td")[1].textContent = "Lovelace";
// clonedRow.querySelectorAll("td")[2].textContent = "10";
table.appendChild(clonedRow);
Repite el proceso dentro de un bucle y tendrás tu tabla completa en milisegundos. Este enfoque mantiene el HTML limpio de lógica y hace que la parte dinámica se concentre en el script, lo que mejora mantenibilidad y rendimiento.

Declarative Shadow DOM con template: shadowrootmode
Además del uso clásico, <template> permite crear Shadow DOM de forma declarativa mediante el atributo shadowrootmode. Si lo defines con «open» o «closed» dentro de un contenedor, el contenido del template se adjunta como árbol sombra, encapsulando estilos y estructura sin necesidad de JavaScript.
<h2>Soy el título externo</h2>
<div class="container">
<template shadowrootmode="open">
<style>h2 { color: red; }</style>
<h2>Soy el título interno</h2>
</template>
</div>
Detalles importantes: con shadowrootmode el template deja de ser inerte y se muestra inmediatamente; los estilos internos solo afectan al árbol sombra, el h2 externo no hereda ese CSS. Si usas «closed», no podrás acceder al Shadow DOM desde JavaScript, lo que incrementa el aislamiento.
Esta técnica es ideal para aislar componentes y evitar fugas de estilo. Úsala cuando necesites encapsulación fuerte y quieras evitar dependencias de librerías o runtime adicional, manteniendo el HTML como fuente de verdad.
Internet Explorer no implementó <template> ni su API. Con HTML5Shiv (incluido en Modernizr) puedes “presentar” elementos HTML5 desconocidos, pero ojo: esto habilita el elemento a nivel de marcado y estilos, no la propiedad .content ni el comportamiento inerte.
La diferencia práctica es que, con el shiv, el navegador crea el elemento vía document.createElement() y le aplica display:none de forma predeterminada. Eso puede provocar un breve destello si el estilo cambia, y, sobre todo, no tendrás el API moderna para clonar el fragmento. Para un soporte real necesitarías un polyfill específico de template o, directamente, degradar funcionalidad.
Buenas prácticas de organización, rendimiento y accesibilidad
Distribuye los templates cerca de su área de uso o en una sección dedicada (por ejemplo, al final del body). Evita anidar plantillas enormes y difíciles de leer; prefiere piezas pequeñas y composables que puedas combinar con JavaScript.
Usa ids claros (p. ej., «tpl-card-producto») y, si necesitas variantes, apóyate en data-atributos y clases. Cuando clones e insertes, ajusta texto con textContent y atributos con setAttribute para prevenir XSS, especialmente si los datos vienen del servidor.
En rendimiento, recuerda que dentro de <template> las imágenes no cargan hasta la activación, lo que reduce el coste inicial. No obstante, si vas a clonar cientos de nodos, hazlo en lotes y cuelga el fragmento ya preparado de una sola vez para minimizar repaints.
Para accesibilidad, completa roles y aria-atributos tras el clonado si tu patrón lo requiere (por ejemplo, filas seleccionables, tarjetas con botones). Y no olvides pruebas con lectores de pantalla: los nodos nuevos deben integrarse con el foco y el orden del DOM.
Plantillas base (boilerplate) en HTML5 para arrancar proyectos
El concepto “boilerplate” describe secciones de código repetitivas que usas como punto de partida. En HTML, un buen esqueleto inicial reúne doctype, idioma, meta esenciales, estilos y scripts; te ahorra tiempo y garantiza consistencia entre páginas.
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>HTML5 Boilerplate</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<script src="index.js"></script>
</body>
</html>
El doctype moderno (<!DOCTYPE html>) activa el modo estándar del navegador. El atributo lang en <html> ayuda a SEO y accesibilidad al indicar el idioma principal, facilitando la pronunciación correcta en lectores de pantalla.
meta charset=»UTF-8″ es la codificación recomendada para soportar caracteres y símbolos de prácticamente cualquier idioma. Con meta name=»viewport» adaptas el ancho al dispositivo y bloqueas el zoom por defecto con initial-scale=1, clave para layouts responsive.
meta http-equiv=»X-UA-Compatible» content=»ie=edge» marcó la compatibilidad con IE en su día; hoy su impacto es residual, pero aún aparece en algunos esqueletos. No olvides <title> con un título descriptivo y un <link rel=»stylesheet»> a tu CSS principal.
En cuanto a scripts, coloca por defecto tus referencias justo antes de </body> para evitar bloquear el render. Cuando necesites JS crítico en el head, intenta que sea ligero, añade defer donde proceda y mide el efecto en LCP y TTI.
Metadatos para SEO y redes: Open Graph, Twitter Cards e iconos
Si tu contenido se comparte, conviene añadir metadatos de Open Graph y Twitter Cards. Estos campos enriquecen la vista previa (título, descripción, imagen), lo que puede mejorar el CTR en redes y mensajería, además de aportar contexto a buscadores.
<meta property="og:title" content="Template HTML5 básico" />
<meta property="og:type" content="website" />
<meta property="og:url" content="https://www.ejemplo.com/pagina" />
<meta property="og:description" content="Template HTML5 para proyectos" />
<meta property="og:image" content="/images/ogimage.png" />
<meta name="twitter:card" content="summary" />
<meta name="twitter:site" content="@tuusuario" />
<meta name="twitter:creator" content="@autoria" />
Completa la identidad visual con favicons y apple-touch-icon, incluyendo variantes SVG y PNG para diferentes contextos. Estas piezas son pequeñas, pero aportan profesionalidad y coherencia a la marca, especialmente en dispositivos móviles y pestañas del navegador.
Un apunte extra: demos y recursos
Si quieres ver un flujo de trabajo completo con <template> y clonación dinámica, hay ejemplos públicos en CodePen, como el de sergiodxa: https://codepen.io/sergiodxa/pen/EaNwVz. Fijarte en cómo organizan el HTML, el JS de clonación y la manipulación de nodos te ayudará a adoptar patrones sólidos desde el minuto uno.
Trabajar con la etiqueta template en HTML5 te permite separar estructura y datos de forma elegante, activar contenido cuando conviene y encapsularlo si necesitas Shadow DOM, todo ello con un impacto positivo en rendimiento, mantenibilidad y limpieza del código. Acompañado de un buen boilerplate y metadatos bien definidos, tendrás una base moderna para proyectos escalables en la que tu UI se compone a demanda sin sorpresas.
Tabla de Contenidos
- ¿Qué es la etiqueta template y por qué es tan útil?
- Características clave de <template>
- Compatibilidad de navegadores y cómo detectar soporte
- Crear tu primer template con HTML normal
- Activar un template: importNode, cloneNode y .content
- Ejemplo práctico: completar una tabla con filas de un template
- Declarative Shadow DOM con template: shadowrootmode
- Compatibilidad con IE y navegadores antiguos: HTML5Shiv y matices
- Buenas prácticas de organización, rendimiento y accesibilidad
- Plantillas base (boilerplate) en HTML5 para arrancar proyectos
- Metadatos para SEO y redes: Open Graph, Twitter Cards e iconos
- Un apunte extra: demos y recursos