Skip to content
This page has been auto-translated and may contain errors.View in English

HTML semántico ​

docs.scrimba.com

Dos páginas pueden verse idénticas y estar construidas de forma muy distinta por debajo. Una usa elementos que llevan el nombre de lo que contienen: un encabezado, una navegación, un área principal. La otra envuelve todo en la misma caja anónima y depende de nombres de clase para diferenciarlas. En pantalla no puedes notar la diferencia. En cualquier otro sentido, no son la misma página en absoluto. Elegir los elementos según su significado es de lo que trata el HTML semántico.

Qué significa "semántico" ​

Semántico significa "relacionado con el significado". Un elemento semántico es uno cuyo nombre dice qué es su contenido. Un párrafo va dentro de un <p> porque es un párrafo. Un menú de navegación va dentro de un <nav> porque es navegación. La etiqueta nombra la cosa.

Podrías construir casi cualquier página con una sola caja genérica y hacer que se vea bien con estilos. Pero entonces nada en la página diría qué es. Elegir el elemento que nombra el contenido es como etiquetar las cajas cuando te mudas de casa. Todo cabría igual en cajas sin etiquetar, pero las etiquetas son lo que permite que cualquier otra persona, o un navegador, entienda qué hay dentro sin tener que abrir cada una.

Un elemento es semántico cuando su nombre describe el significado de su contenido, no su apariencia. <nav>, <article> y <button> son semánticos: te dicen para qué es el contenido. <div> y <span> no lo son: son contenedores genéricos que por sí solos no significan nada.

La ventaja es que el significado queda registrado en el marcado, donde otras herramientas pueden leerlo. Un navegador sabe que un <button> se puede hacer clic y enfocar con el teclado sin que tú agregues nada. Un lector de pantalla puede anunciar un <nav> como una región de navegación. Los buscadores tratan un <article> como un fragmento de contenido autocontenido. Nada de eso funciona si el elemento es un <div> con estilos, porque un <div> no promete nada sobre lo que contiene.

La semántica es la diferencia entre un elemento que transmite significado y uno que solo transmite píxeles. Cuando escribes <nav>, no solo estás dibujando una caja, estás afirmando un hecho sobre el documento: esta región es navegación. Ese hecho queda registrado en el árbol de accesibilidad (la estructura paralela que el navegador construye junto al DOM, describiendo el rol y el estado de cada elemento para la tecnología de asistencia), y es sobre lo que actúan herramientas distintas a un usuario que ve la pantalla y usa el mouse.

La prueba práctica es la sustitución. Si reemplazaras un elemento por un <div> sin nada más y le dieras estilos para que se vea idéntico, ¿qué perderías? Para un <p> o un contenedor decorativo, nada relevante. Para un <button>, perderías el foco con el teclado, el manejo de las teclas Enter y Espacio, y el anuncio de "botón" para un lector de pantalla, y tendrías que reconstruir todo eso a mano. Esa diferencia es la semántica: el comportamiento y el significado que el navegador te da gratis porque el nombre del elemento le dijo qué era el contenido. Elegir el elemento con nombre no es una preferencia de estilo, es la forma más barata de obtener el comportamiento correcto.

JunoQué significa 'semántico' Semántico significa que la etiqueta lleva el nombre de lo que contiene: un párrafo en un <p>, un menú en un <nav>. Podrías poner todo en cajas simples y darles estilo para que se vean igual, pero entonces nada diría qué es. Piénsalo como etiquetar tus cajas de mudanza para que cualquiera sepa qué hay dentro.
JunoQué significa 'semántico' Un elemento semántico nombra su significado, un <div> no nombra nada. La ganancia es que los navegadores, los lectores de pantalla y los buscadores pueden leer el significado directamente del marcado. Elige el elemento que describe el contenido, y reserva <div> para cuando realmente no hay nada que describir.
JunoQué significa 'semántico' Aplica la prueba de sustitución: cambia el elemento por un <div> con estilos y pregúntate qué perdiste. Si la respuesta es el foco con el teclado, un rol en el árbol de accesibilidad o un anuncio del lector de pantalla, eso es la semántica que estabas obteniendo gratis. Reconstruirla a mano siempre implica más trabajo que usar el elemento con nombre.

Los elementos de referencia (landmarks) ​

Existe un puñado de elementos para marcar las grandes regiones de una página. Son los primeros a los que recurres:

  • <header> es la parte superior de una página o sección: un logo, un título, una introducción.
  • <nav> es un conjunto de enlaces de navegación, como el menú principal.
  • <main> es el contenido principal, la razón por la que existe la página.
  • <section> es un bloque agrupado de contenido relacionado, normalmente con su propio encabezado.
  • <article> es una pieza autocontenida que tendría sentido por sí sola, como una entrada de blog o una noticia.
  • <aside> es contenido secundario: enlaces relacionados, una nota, un anuncio publicitario.
  • <footer> es la parte inferior de una página o sección: derechos de autor, datos de contacto, letra pequeña.

La regla es siempre la misma. Si una región es navegación, va dentro de un <nav>, no de un <div>. Si es el pie de página, va dentro de un <footer>. Nombras la región con el elemento que le corresponde.

html
<header>
  <h1>La Cocina de Mara</h1>
  <nav>
    <a href="/recetas">Recetas</a>
    <a href="/acerca">Acerca de</a>
  </nav>
</header>
<main>
  <h2>Cenas de entre semana</h2>
  <p>Comidas rápidas que puedes hacer después del trabajo.</p>
</main>
<footer>
  <p>Hecho en Ciudad de México.</p>
</footer>

Siete elementos dividen una página en sus regiones principales, y juntos se llaman elementos de referencia (landmarks) porque cada uno marca una región a la que un lector o una herramienta puede navegar:

  • <header> introduce al contenedor más cercano: en la parte superior de la página contiene la identidad del sitio, dentro de un <article> contiene el título y el autor de ese artículo.
  • <nav> envuelve un bloque de enlaces de navegación. Úsalo para los importantes, el menú principal o una tabla de contenidos, no para cualquier enlace suelto de la página.
  • <main> contiene el contenido principal del documento, la parte única de esta página en lugar de la que se repite en todo el sitio.
  • <section> agrupa contenido relacionado que pertenece junto, normalmente introducido por un encabezado.
  • <article> es una unidad completa e independiente: una publicación, un comentario, una tarjeta de producto. La prueba es si tendría sentido sacarlo y mostrarlo por sí solo.
  • <aside> contiene contenido tangencial a lo que lo rodea: una barra lateral, una cita destacada, enlaces relacionados.
  • <footer> cierra al contenedor más cercano con el material de remate: autoría, enlaces, texto legal.

La idea clave es que la mayoría de estos son contextuales. Un <header> y un <footer> describen aquello dentro de lo que están, así que una sola página puede tener varios de cada uno, un par para la página y otro para cada <article>. <main> es la excepción, que se cubre en la siguiente sección.

html
<article>
  <header>
    <h2>Sopa de tomate asado</h2>
    <p>Por Camila, 20 minutos</p>
  </header>
  <p>Corta los tomates a la mitad y ásalos hasta que estén suaves.</p>
  <footer>
    <p>Rinde para cuatro.</p>
  </footer>
</article>

Los siete elementos de región son los landmarks de HTML: elementos que exponen una región navegable en el árbol de accesibilidad. Cada uno se asocia a un rol que la tecnología de asistencia puede listar y entre los que puede saltar, que es la razón real por la que importan más allá de verse ordenados en el código fuente.

  • <header> se asocia al rol banner a nivel de página, pero no cuando está anidado dentro de un <article>, <aside>, <main>, <nav> o <section>, donde es solo un grupo introductorio sin rol de landmark.
  • <footer> funciona igual en espejo: contentinfo a nivel de página, y un grupo simple cuando está anidado dentro de uno de esos elementos de sección.
  • <nav> es el rol navigation. Una página suele tener más de uno, un menú principal y una lista de contenidos dentro de la página, que es donde entra el etiquetado que se ve más abajo.
  • <main> es el rol main y marca el contenido principal. Hay uno por página.
  • <aside> es el rol complementary: contenido que apoya al contenido principal pero se mantiene aparte de él.
  • <section> se convierte en un landmark de tipo region solo cuando tiene un nombre accesible, normalmente a partir de un encabezado asociado a él; un <section> sin nombre no expone ningún landmark y, para el árbol de accesibilidad, es prácticamente como un <div>.
  • <article> lleva el rol article, una composición autocontenida, que las herramientas pueden enumerar pero que no es un landmark de navegación en el mismo sentido que los demás.

El objetivo de diseño es que un usuario que no ve pueda recorrer el documento tan rápido como un usuario que ve recorre el diseño con la vista. Un lector de pantalla puede generar una lista de todos los landmarks y permitir que el usuario salte directamente a "main" o "navigation" sin escuchar el contenido intermedio. Eso solo funciona si las regiones están marcadas con elementos de landmark reales. Un documento hecho todo de <div>s no produce ningún landmark, así que la única forma de recorrerlo es de arriba a abajo.

html
<body>
  <header>            <!-- banner: a nivel de página -->
    <nav>...</nav>    <!-- navigation -->
  </header>
  <main>              <!-- main: la única región principal -->
    <article>...</article>
    <aside>...</aside> <!-- complementary -->
  </main>
  <footer>...</footer> <!-- contentinfo: a nivel de página -->
</body>
JunoLos elementos de referencia (landmarks) Hay siete etiquetas de región que vale la pena conocer: <header>, <nav>, <main>, <section>, <article>, <aside> y <footer>. Cada una nombra una parte de la página, y eliges la que coincida con la región que estás construyendo. No tienes que memorizarlas hoy, van a aparecer una y otra vez hasta que se te queden.
JunoLos elementos de referencia (landmarks) Siete elementos dividen una página en regiones, y la mayoría describen aquello dentro de lo que están, así que <header> y <footer> pueden aparecer más de una vez. La prueba del <article> me ahorró mucha duda: ¿esto se sostendría por sí solo si lo sacaras? Si sí, es un article; si es un bloque agrupado con un encabezado, es un section.
JunoLos elementos de referencia (landmarks) Estos son los landmarks, y cada uno se asocia a un rol al que un lector de pantalla puede saltar, por eso superan a una pila de <div>s. Dos detalles que hay que tener presentes: <header> y <footer> solo se convierten en los landmarks banner y contentinfo a nivel superior, y un <section> solo es landmark cuando tiene un nombre accesible. Un section sin nombre es básicamente un div para la tecnología de asistencia.

div y span, el recurso sin semántica ​

No toda parte de una página tiene un significado que valga la pena nombrar. A veces solo necesitas una caja para agrupar cosas y darles estilo, o envolver unas palabras para pintarlas. Para eso existen dos elementos simples sin significado propio.

<div> es un bloque genérico: un contenedor vacío que usas cuando ningún otro elemento encaja. <span> es la misma idea para un pequeño fragmento de texto dentro de una línea. Ninguno dice nada sobre su contenido. Existen solo como ganchos para dar estilo y agrupar.

html
<p>El total de hoy es <span class="price">$800.00</span>.</p>

<div class="card">
  <h2>Oferta especial</h2>
  <p>Dos por uno en toda la pasta.</p>
</div>

El <span> envuelve un precio para que puedas pintarlo. El <div> agrupa una tarjeta para que puedas ponerle un borde. Recurre a estos solo cuando nada más significativo encaje, porque no le dicen nada al navegador sobre lo que hay dentro.

<div> y <span> son los dos elementos sin ningún significado, y exactamente para eso existen. Un <div> es un contenedor genérico de bloque; un <span> es un contenedor genérico en línea. Los usas como ganchos de estilo: un lugar donde colgar una clase o un id cuando necesitas agrupar o seleccionar contenido pero no hay nada significativo que decir sobre él.

html
<div class="grid">
  <article class="card">...</article>
  <article class="card">...</article>
</div>

El <div class="grid"> existe solo para acomodar las tarjetas en una cuadrícula. Ese es un trabajo de presentación, no de significado, así que un <div> es la elección correcta, no un recurso por el que debas sentirte mal. El error es lo contrario: usar un <div> para algo que sí tiene significado. Un <div> en el que se hace clic debería ser un <button>, un <div> lleno de enlaces de navegación debería ser un <nav>, un <div> que envuelve una publicación completa debería ser un <article>. Cuando no hay significado, solo una necesidad de diseño o estilo, <div> y <span> son la respuesta correcta.

<div> y <span> son los elementos semánticamente vacíos: un contenedor genérico de bloque y uno genérico en línea, respectivamente, sin rol en el árbol de accesibilidad y sin significado para ninguna herramienta. Son la elección correcta para un único trabajo, un gancho de presentación: un elemento que existe únicamente para aplicar estilos o agrupar hijos con fines de diseño, y que no lleva ninguna información que un lector de pantalla o un buscador deba anunciar jamás.

El valor de tener un elemento completamente sin significado es que mantiene honestos a los elementos que sí tienen significado. Un contenedor de cuadrícula, una fila de flexbox, un contexto de posicionamiento: son necesidades reales sin contenido semántico, y forzar un elemento significativo sobre ellas sería una mentira en el marcado. Un <section> usado solo para un color de fondo afirma ser una región que no es. Así que la regla funciona en ambos sentidos. No recurras a un <div> cuando un elemento con nombre encaje, y no recurras a un elemento con nombre cuando lo único que necesitas es una caja.

El modo de fallo que hay que vigilar es el <div> interactivo: un elemento al que se le agrega un manejador de clic en JavaScript para que actúe como un botón o un enlace. Se renderiza y responde al clic del mouse, así que parece terminado, pero no tiene rol, no está en el orden de tabulación, no responde a Enter ni a Espacio, y un lector de pantalla no anuncia nada. Recrear todo eso con tabindex, role y manejadores de teclas es una reimplementación frágil de un <button> que ya existe. Si algo se comporta como un control, usa el elemento de control; reserva <div> y <span> para las partes que son solo píxeles.

Junodiv y span, el recurso sin semántica<div> es una caja simple y <span> es un envoltorio simple para unas cuantas palabras, y ninguno de los dos significa nada. Úsalos cuando solo necesites agrupar o dar estilo a algo y ningún elemento con nombre encaje. Si la cosa sí tiene un significado, como un menú o un botón, usa el elemento correspondiente en su lugar.
Junodiv y span, el recurso sin semántica Un <div> o <span> es la elección correcta cuando el único trabajo es el diseño o el estilo, sin significado que afirmar. No te sientas mal por usarlos, siéntete mal por lo contrario: un <div> en el que se hace clic y que debería ser un <button>, o un <div> envoltorio que debería ser un <article>. Elemento vacío para significado vacío, elemento con nombre para significado real.
Junodiv y span, el recurso sin semántica<div> y <span> no tienen rol en el árbol de accesibilidad, y precisamente por eso son correctos para ganchos de estilo puros y equivocados para cualquier cosa con significado. El que te va a morder es el <div> interactivo con un manejador de clic: sin foco, sin teclado, sin anuncio, y un montón de parches de tabindex y role para simular lo que <button> te da gratis. Si se comporta como un control, hazlo el control.

Elegir el elemento correcto ​

Cuando no estés seguro de qué elemento usar, hazte una pregunta sencilla: ¿qué es esta cosa? No cómo se ve, sino qué es. La respuesta casi siempre te da el nombre del elemento. Una fila de enlaces en la parte superior es navegación, así que es un <nav>. Un bloque de letra pequeña en la parte inferior es un pie de página, así que es un <footer>. Un precio al que quieres darle color no es realmente nada por sí mismo, así que es un <span>.

Empieza desde el significado, y recurre a un <div> o <span> solo cuando la respuesta real sea "solo es una caja". Adquirir este hábito desde temprano hace que tus páginas se describan a sí mismas, y eso da fruto en el momento en que tú o cualquier otra persona tengan que volver a leer el marcado.

Elegir el elemento correcto es una decisión breve que puedes tomar cada vez. Pregúntate qué es el contenido, y deja que la respuesta escoja el elemento:

  • ¿Es algo completo por sí mismo que tendría sentido por su cuenta? <article>.
  • ¿Es un bloque agrupado de contenido relacionado con un encabezado? <section>.
  • ¿Es navegación? <nav>. ¿Una introducción a una región? <header>. ¿Un cierre? <footer>.
  • ¿Es contenido lateral que apoya al contenido principal? <aside>.
  • ¿No hay significado, solo una necesidad de diseño o estilo? <div>, o <span> dentro de una línea.

La bifurcación más difícil es <section> contra <article> contra <div>. Recórrela en orden. Si el bloque podría sostenerse por sí solo, es un <article>. Si no, pero es un grupo temático con su propio encabezado, es un <section>. Si no tiene encabezado ni significado, y existe solo para tener estilo o diseño, es un <div>. Un <section> casi siempre debería tener un encabezado; si no se te ocurre uno, es una señal fuerte de que en realidad querías un <div>.

html
<main>
  <section>
    <h2>Últimas publicaciones</h2>
    <article>
      <h3>Por qué me cambié al HTML puro</h3>
      <p>...</p>
    </article>
    <article>
      <h3>El caso en contra de los frameworks pesados</h3>
      <p>...</p>
    </article>
  </section>
</main>

Aquí el <section> es un grupo temático, "últimas publicaciones", y cada publicación dentro de él es un <article> porque se sostiene por sí sola. La anidación refleja el significado.

Elegir bien se reduce a leer primero el significado y nunca el diseño visual, pero unas cuantas reglas hacen mecánicas las decisiones más comunes.

Hay exactamente un <main> por página. Marca el contenido principal, la parte única de esta página en lugar del encabezado, la navegación y el pie de página que se repiten en todo el sitio. Más de un <main> en el árbol de accesibilidad le da a un usuario de lector de pantalla dos destinos "main" y ninguna forma de saber cuál es el real, así que mantenlo singular. Todo lo que sea del sitio en general va fuera de él.

La otra regla que importa una y otra vez es etiquetar los landmarks repetidos. Cuando una página tiene dos elementos del mismo tipo de landmark, un <nav> principal y una tabla de contenidos dentro de la página, ambos se anuncian como "navigation" y el usuario no puede diferenciarlos. Los distingues con aria-label, un atributo que proporciona un nombre accesible breve para una región sin mostrar nada en pantalla:

html
<nav aria-label="Principal">
  <a href="/">Inicio</a>
  <a href="/blog">Blog</a>
</nav>

<nav aria-label="En esta página">
  <a href="#intro">Introducción</a>
  <a href="#setup">Configuración</a>
</nav>

Ahora las dos regiones se anuncian como "Principal navigation" y "En esta página navigation", y la lista de landmarks se vuelve utilizable. Aplica el mismo etiquetado a cualquier landmark repetido, incluidos <aside> o <section>. En el caso de <section>, recuerda que solo se convierte en landmark cuando tiene un nombre accesible, sea a partir de un encabezado asociado o de un aria-label.

La metaregla detrás de todo esto: el marcado es una descripción legible por máquina del documento, leída por lectores de pantalla, rastreadores de buscadores, herramientas de modo lectura y tu propio yo del futuro. Elegir los elementos según su significado es lo que hace verdadera esa descripción. El diseño visual es trabajo de CSS, y cada vez que te descubras elegiendo un elemento por cómo se ve, te has metido en el terreno de CSS usando la herramienta equivocada.

JunoElegir el elemento correcto Cuando estés atascado, pregúntate qué es la cosa, no cómo se ve. La navegación es un <nav>, la letra pequeña es un <footer>, una caja simple a la que quieres darle estilo es un <div>. Empieza siempre desde el significado, y tus páginas terminarán describiéndose a sí mismas.
JunoElegir el elemento correcto Recorre la pequeña lista: se sostiene por sí solo es un <article>, grupo temático con encabezado es un <section>, sin significado y solo estilo es un <div>. El criterio que resuelve la mayoría de los debates entre section y div: si no puedes nombrarle un encabezado, en realidad querías un <div>. Deja que el significado escoja la etiqueta y la anidación se resuelve sola.
JunoElegir el elemento correcto Dos reglas cargan con la mayor parte del peso: exactamente un <main> por página, y etiquetar los landmarks repetidos con aria-label para que dos navs no digan ambos "navigation". Ten presente que un <section> solo es landmark cuando tiene un nombre accesible. Elige los elementos según su significado y deja la apariencia para CSS, porque en el momento en que eliges una etiqueta por cómo se renderiza, estás haciendo el trabajo de CSS con la herramienta equivocada.