Semántica HTML5: la guía completa para escribir HTML que funciona de verdad
article, section, nav, aside, header, footer: qué representa realmente cada uno, cuándo NO usarlos, y por qué un div con onclick nunca es lo mismo que un button.
Un <div> con onclick que hace de botón. Un <span> en negrita que hace de título. Tres niveles de <div class="wrapper">, <div class="inner">, <div class="content"> para lo que en realidad es una barra lateral. Ese patrón tiene nombre desde hace más de una década —divitis— y sigue apareciendo en proyectos nuevos en 2026, no porque HTML5 no resolviera el problema, sino porque usar <div> para todo nunca da un error. El navegador lo renderiza igual, el CSS lo estiliza igual… hasta que alguien navega con lector de pantalla, un buscador intenta entender de qué trata la página, o el propio equipo intenta mantener ese HTML seis meses después.
Este artículo no es una lista de las quince etiquetas semánticas de HTML5. Es una guía de criterio: qué representa cada elemento en la especificación, cuándo usarlo y cuándo no, y qué se rompe de verdad —no en teoría— cuando se usa mal.
Qué significa “semántica” aquí, exactamente
Un <div> y un <article> pueden ser visualmente idénticos con el CSS adecuado. La diferencia no está en pantalla: está en lo que cada uno comunica a quien —o lo que— lee el HTML sin verlo renderizado. Hay al menos tres consumidores de esa información además del navegador visual:
- Lectores de pantalla y otras tecnologías asistivas, que construyen un árbol de accesibilidad a partir del DOM y usan elementos como
<nav>,<main>o<aside>como landmarks: puntos de navegación rápida que permiten saltar directamente a una sección sin escuchar todo el contenido intermedio. Ese árbol es paralelo al DOM visual y lo explicamos con detalle en el DOM explicado a fondo. - Rastreadores de buscadores, que usan la estructura para entender qué es el contenido principal, qué es navegación reutilizable y qué es un artículo autocontenido susceptible de aparecer como resultado independiente.
- Otros desarrolladores (incluido tú, dentro de seis meses), que leen
<header>,<article>y<footer>y entienden la función de cada bloque sin necesidad de nombres de clase descriptivos ni comentarios.
<div> y <span> no están mal: son, literalmente, elementos sin significado propio, pensados para agrupar contenido cuando no hay ningún elemento semántico apropiado o cuando el agrupamiento es puramente de estilo. El problema no es que existan, es usarlos por defecto cuando sí existe un elemento que describe mejor la función real del bloque.
El contenido de sección: article, section, nav y aside
Estos cuatro son sectioning content según la especificación: cada uno delimita una región del documento con un propósito distinto, y confundirlos es el error más común.
<article>: independiente y distribuible por sí solo
La especificación lo define como una composición completa y autónoma, pensada para poder distribuirse o reutilizarse de forma independiente: un post de blog, una noticia, un comentario de usuario, la tarjeta de un producto. La pregunta que decide si algo es un <article> es simple: ¿tendría sentido si lo sacara de esta página y lo pegara en otra? Un post de este blog, sí. La barra de navegación del sitio, no.
<article> admite anidamiento, y cuando lo hace, el artículo interno representa contenido relacionado con el externo —el caso típico son los comentarios dentro de un post—:
<article class="post">
<header>
<h1>Título del post</h1>
<p>Por <a href="/autor">Nombre</a> · <time datetime="2026-02-16">16 feb 2026</time></p>
</header>
<p>Contenido del artículo…</p>
<article class="comentario">
<h3>Comentario de un lector</h3>
<p>Aporta un matiz interesante…</p>
</article>
</article>
<section>: agrupación temática, no contenedor de estilo
Aquí es donde más se abusa del elemento. <section> representa una sección genérica y autónoma de un documento que no tiene ya un elemento más específico para representarla. La propia documentación de MDN es explícita al respecto: si lo estás usando solo como gancho de estilos, sin que tenga sentido temático propio, el elemento correcto es <div>.
Una regla práctica que evita casi todos los errores: una <section> casi siempre debería llevar un encabezado (<h2>-<h6>) que la describa. Si no puedes ponerle un título con sentido, probablemente no es una <section>.
<!-- Mal: section usado solo para aplicar un fondo distinto -->
<section class="bg-gris">
<div class="logo">…</div>
</section>
<!-- Bien: section con propósito temático propio y encabezado -->
<section>
<h2>Preguntas frecuentes</h2>
<p>…</p>
</section>
<nav>: bloques principales de navegación, no cualquier grupo de enlaces
<nav> marca una sección cuyo propósito es ofrecer enlaces de navegación —el menú principal, una tabla de contenidos, la paginación de un listado—. Y aquí hay un matiz que se pasa por alto a menudo: MDN es explícito en que no todos los grupos de enlaces necesitan un <nav>. Un puñado de enlaces sueltos en el pie de página no necesitan envolverse en uno; forzarlo diluye el valor del elemento para cuando de verdad importa.
Cuando una página tiene varios <nav> (navegación del sitio + tabla de contenidos del artículo, por ejemplo), cada uno debería tener un nombre accesible distinto con aria-label, porque de otro modo un lector de pantalla los anuncia a todos como “navigation” sin forma de diferenciarlos:
<nav aria-label="Principal">…</nav>
<nav aria-label="Tabla de contenidos">…</nav>
<aside>: relacionado, pero separable
<aside> representa contenido tangencialmente relacionado con lo que lo rodea: una barra lateral, una cita destacada extraída del propio texto, publicidad, un widget de “artículos relacionados”. La clave es que podría eliminarse sin que el contenido principal pierda sentido. Si el contenido de tu <aside> es en realidad imprescindible para entender el artículo, no es un aside: es parte del contenido principal.
header, footer y main: no son “contenido de sección”
Un error habitual es tratar <header> y <footer> como si delimitaran secciones temáticas igual que <article> o <section>. No lo hacen: son contenido introductorio y de cierre respectivamente, y no afectan a cómo se estructura el resto del documento. Esto tiene una consecuencia práctica poco conocida: puedes tener más de un <header> y más de un <footer> por página, uno a nivel de documento y otros dentro de cada <article> o <section>, y son perfectamente válidos.
<main>, en cambio, es único: representa el contenido principal y dominante de la página, y solo debe haber uno visible por documento. Su rol de accesibilidad (main) es uno de los landmarks que más agradecen los usuarios de lector de pantalla, porque les permite saltar directamente al contenido real sin atravesar cabecera y menú en cada página que visitan.
Una incorporación reciente que vale la pena conocer: <search>
Durante años, marcar visualmente una caja de búsqueda no tenía ningún elemento semántico propio: se resolvía con <div role="search"> o, más a menudo, sin ninguna marca en absoluto. El elemento <search>, con soporte ya consolidado en Chrome, Firefox y Safari desde finales de 2023, cubre exactamente ese hueco: agrupa los controles de un formulario de búsqueda o filtrado —del sitio, de la página actual, o de una sección de contenido— y expone automáticamente el landmark search a las tecnologías asistivas.
<search>
<form action="/buscar" method="get">
<label for="q">Buscar en el sitio</label>
<input type="search" id="q" name="q" />
<button type="submit">Buscar</button>
</form>
</search>
Importante: <search> envuelve los controles de búsqueda, no los resultados. Los resultados de una búsqueda son contenido principal y van fuera de él, normalmente dentro de <main>.
El mito del “outline automático” que nunca existió en la práctica
Cuando HTML5 introdujo los elementos de sección, la especificación original venía acompañada de un algoritmo de outline: la idea de que anidar <section> con sus propios <h1> generaría automáticamente un esquema de documento correcto, con el nivel de encabezado ajustándose según la profundidad de anidamiento, sin que tuvieras que escribir <h2>, <h3>… a mano.
Ese algoritmo nunca lo implementó ningún navegador a efectos de accesibilidad. Los navegadores sí adoptaron parte del comportamiento visual (el tamaño con el que se renderiza un <h1> anidado más profundamente cambia por defecto), pero el árbol de accesibilidad que consumen los lectores de pantalla siguió tratando cada <h1> como un encabezado de nivel 1, sin importar cuántos <section> lo envolvieran. En 2022, el WHATWG terminó eliminando formalmente el algoritmo de la especificación, después de años de que herramientas de accesibilidad y navegadores lo ignoraran de facto.
Accesibilidad: landmarks y el detalle que casi nadie comprueba
Cada elemento semántico de sección tiene un rol ARIA implícito que el navegador expone automáticamente, sin que tengas que añadir role="..." a mano: <nav> → navigation, <main> → main, <aside> → complementary, <article> → article. <header> y <footer> mapean a banner y contentinfo respectivamente, pero solo cuando son hijos directos de <body> — un <header> dentro de un <article> no es un landmark de página, es una cabecera de ese artículo concreto.
El matiz que casi nadie comprueba es el de <section>: solo obtiene el rol de landmark region si tiene un nombre accesible, ya sea mediante aria-labelledby apuntando a su encabezado o con aria-label. Una <section> sin encabezado ni etiqueta no aparece como región navegable para un lector de pantalla — semánticamente, se comporta como un <div> a efectos de accesibilidad, aunque el navegador la haya “aceptado” sin quejarse.
<section aria-labelledby="faq-heading">
<h2 id="faq-heading">Preguntas frecuentes</h2>
<p>…</p>
</section>
Este es también el motivo por el que un <div onclick="..."> nunca sustituye a un <button> real: por muy idéntico que se vea con CSS, el árbol de accesibilidad que construye el navegador —el que explicamos en detalle en el DOM explicado a fondo— nunca generará la misma entrada. Un <div> no es enfocable con teclado por defecto, no dispara click al pulsar Enter o espacio, y no se anuncia como “botón” a ningún lector de pantalla, aunque tenga exactamente el mismo aspecto visual.
SEO: lo que la semántica sí hace y lo que no
Conviene ser precisos aquí, porque circula bastante mito. Usar <article> en lugar de <div> no es un factor de ranking directo que Google puntúe como tal — no existe evidencia pública de que el algoritmo asigne puntos por usar la etiqueta “correcta”. Lo que sí hace la semántica es facilitar que el rastreador interprete correctamente la estructura: qué es contenido principal frente a navegación reutilizable, dónde empieza y termina una pieza de contenido autocontenida, cuál es la jerarquía temática de la página. Esa interpretación correcta influye indirectamente en cómo se generan fragmentos enriquecidos, en la relevancia percibida del contenido principal, y en la facilidad con la que el rastreador distingue plantilla de contenido único.
Dicho de otro modo: el HTML semántico no es una técnica de SEO en sí misma, es la base sobre la que las técnicas de SEO —marcado de datos estructurados, encabezados bien jerarquizados, contenido accesible— funcionan de forma fiable. Un sitio con HTML semántico correcto no va a subir posiciones por eso solo; un sitio con <div> genéricos por todas partes sí está poniéndole trabajo extra innecesario al rastreador para entender algo que podría haber sido explícito.
Divitis en la práctica: antes y después
<!-- Antes: HTML sin significado, solo estructura visual -->
<div class="header">
<div class="logo">Mi sitio</div>
<div class="menu">
<div class="menu-item"><a href="/">Inicio</a></div>
<div class="menu-item"><a href="/blog">Blog</a></div>
</div>
</div>
<div class="content">
<div class="post">
<div class="post-title">Título</div>
<div class="post-body">Contenido…</div>
</div>
</div>
<div class="footer">© 2026</div>
<!-- Después: mismo aspecto visual con el CSS adecuado, significado real -->
<header>
<p class="logo">Mi sitio</p>
<nav aria-label="Principal">
<ul>
<li><a href="/">Inicio</a></li>
<li><a href="/blog">Blog</a></li>
</ul>
</nav>
</header>
<main>
<article>
<h1>Título</h1>
<p>Contenido…</p>
</article>
</main>
<footer>© 2026</footer>
Nada cambia visualmente si el CSS está bien escrito. Lo que cambia es todo lo que no se ve en pantalla: navegación por teclado y lector de pantalla con landmarks reales, y una estructura que cualquier rastreador o desarrollador nuevo entiende sin necesidad de leer nombres de clase.
Cuándo usar div y span sin ningún remordimiento
No se trata de eliminar <div> y <span> del vocabulario. Son la herramienta correcta cuando el agrupamiento es puramente de presentación y no existe ningún significado semántico que comunicar: un wrapper para aplicar un grid de CSS, un <span> para colorear una palabra dentro de una frase, un contenedor que solo existe para resolver un problema de layout. Forzar <section> o <article> ahí donde un <div> es honesto sobre su propósito es el mismo error que la divitis, solo que en la dirección contraria.
Checklist antes de dar por bueno un HTML
- Un único
<main>visible por página, y un único<h1>que lo describa. - Jerarquía de encabezados sin saltos (
<h2>después de<h1>, nunca<h4>después de<h1>directamente). - Cada
<section>tiene encabezado o, si no puede tenerlo visible,aria-label. - Los
<nav>múltiples llevanaria-labeldistintos entre sí. - Ningún
<div>ni<span>hace de botón, enlace o control de formulario: para eso están<button>,<a href>e<input>. - Antes de publicar, revisa el árbol de accesibilidad en las herramientas de desarrollo del navegador, no solo el resultado visual — es la comprobación más rápida de que la semántica que escribiste es la que realmente se está exponiendo.
Ese último paso es el que más se salta y el que más revela: es fácil que un HTML “se vea bien” y esté comunicando una estructura completamente distinta a la que crees que tiene.
Artículos relacionados
Cómo renderiza el navegador una página web: el pipeline crítico de renderizado
Del HTML en bruto a píxeles en pantalla: parsing, render tree, layout, paint y composición, y por qué cada fase tiene un impacto directo y medible en Core Web Vitals.
SEO técnico para developers: lo que de verdad mueve el ranking en 2026
Separamos el SEO que se decide en el código (rendering, crawling, structured data, Core Web Vitals) del que pertenece a marketing de contenidos.
Optimización de imágenes en la web moderna: formatos, lazy loading y CDN
Formatos de imagen, srcset/sizes, lazy loading nativo y CDN de transformación on-the-fly: la guía técnica completa para dejar de servir imágenes de más.