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 manera muy diferente por debajo. Una usa elementos nombrados según 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 diferenciarlos. En la pantalla no puedes notar la diferencia. En todos los otros aspectos no son la misma página en absoluto. Elegir elementos por su significado es de qué 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 en un <p> porque es un párrafo. Un menú de navegación va en una <nav> porque es navegación. El nombre de la etiqueta nombra la cosa.

Podrías construir casi cualquier página con una sola caja multiusos y hacerla verse 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 seguiría cabiendo en cajas planas sin etiquetar, pero las etiquetas son lo que permite a cualquier otra persona, o a un navegador, entender qué hay dentro sin abrir cada una.

Un elemento es semántico cuando su nombre describe el significado de su contenido, no cómo se ve el contenido. <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 no significan nada por sí solos.

La ventaja es que el significado vive en el marcado, donde otras herramientas pueden leerlo. Un navegador sabe que un <button> es clickeable y enfocable con el teclado sin que añadas nada. Un lector de pantalla puede anunciar una <nav> como una región de navegación. Los motores de búsqueda tratan un <article> como un contenido autocontenido. Nada de eso funciona si el elemento es un <div> estilizado, porque un <div> no promete nada sobre lo que contiene.

La semántica es la diferencia entre un elemento que porta significado y uno que solo porta píxeles. Cuando escribes <nav>, no solo estás dibujando una caja, estás estableciendo un hecho sobre el documento: esta región es navegación. Ese hecho se registra en el árbol de accesibilidad (la estructura paralela que el navegador construye junto al DOM, describiendo el rol y estado de cada elemento para la tecnología de asistencia), y es sobre lo que actúan las herramientas que no son un usuario vidente con ratón.

La prueba práctica es la sustitución. Si reemplazaras un elemento con un <div> desnudo y lo estilizaras para que se vea idéntico, ¿qué perderías? Para un <p> o un envoltorio decorativo, nada significativo. Para un <button>, perderías el enfoque del teclado, el manejo de las teclas Intro y Espacio, y el anuncio de "botón" a un lector de pantalla, y tendrías que reconstruirlo todo a mano. Esa brecha es la semántica: el comportamiento y significado que el navegador te da de forma gratuita porque el nombre del elemento le dice qué es el contenido. Elegir el elemento nombrado 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 se nombra según lo que contiene: un párrafo en un <p>, un menú en una <nav>. Podrías poner todo en cajas planas y estilizarlo para que se vea igual, pero entonces nada dice qué es. Piénsalo como etiquetar tus cajas de mudanza para que cualquiera pueda saber qué hay dentro.
JunoQué significa semántico Un elemento semántico nombra su significado, un <div> no nombra nada. La ventaja es que los navegadores, lectores de pantalla y motores de búsqueda pueden leer el significado directamente del marcado. Usa el elemento que describe el contenido, y mantén <div> para cuando realmente no hay nada que describir.
JunoQué significa semántico Ejecuta la prueba de sustitución: reemplaza el elemento con un <div> estilizado y pregúntate qué perdiste. Si la respuesta es enfoque del teclado, un rol en el árbol de accesibilidad, o un anuncio de lector de pantalla, esa es la semántica que estabas obteniendo gratis. Reconstruirla a mano siempre es más trabajo que usar el elemento nombrado.

Los elementos de referencia

Un puñado de elementos existe para marcar las grandes regiones de una página. Estos son los primeros a los que recurres:

  • <header> es la parte superior de una página o una 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 fragmento agrupado de contenido relacionado, generalmente con su propio encabezado.
  • <article> es una pieza autocontenida que seguiría teniendo sentido por sí sola, como una entrada de blog o una noticia.
  • <aside> es contenido a un lado: enlaces relacionados, una nota, un anuncio.
  • <footer> es la parte inferior de una página o sección: copyright, detalles de contacto, letra pequeña.

La regla es la misma cada vez. Si una región es navegación, va en una <nav>, no en un <div>. Si es el pie de página, va en un <footer>. Nombras la región con el elemento que la coincide.

html
<header>
  <h1>La cocina de María</h1>
  <nav>
    <a href="/recipes">Recetas</a>
    <a href="/about">Acerca de</a>
  </nav>
</header>
<main>
  <h2>Cenas entre semana</h2>
  <p>Comidas rápidas que puedes preparar 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 porque cada uno marca una región a la que un lector o una herramienta puede navegar:

  • <header> introduce su contenedor más cercano: en la parte superior de la página contiene la marca del sitio, dentro de un <article> contiene el título y la línea de crédito de ese artículo.
  • <nav> envuelve un bloque de enlaces de navegación. Úsalo para los significativos, el menú principal o una tabla de contenidos, no para cada enlace aleatorio en la página.
  • <main> contiene el contenido principal del documento, la parte única de esta página en lugar de repetida en todo el sitio.
  • <section> agrupa contenido relacionado que pertenece junto, normalmente introducido por un encabezado.
  • <article> es una unidad completa e independiente: una entrada, un comentario, una tarjeta de producto. La prueba es si seguiría teniendo sentido sacado y mostrado por sí solo.
  • <aside> contiene contenido tangencial a lo que lo rodea: una barra lateral, una cita destacada, enlaces relacionados.
  • <footer> cierra su contenedor más cercano con el material de cierre: autoría, enlaces, texto legal.

La idea clave es que la mayoría de estos son contextuales. Un <header> y un <footer> describen lo que sea que contengan, por lo que una sola página puede contener varios de cada uno, un par para la página y uno para cada <article>. <main> es la excepción, cubierta en la siguiente sección.

html
<article>
  <header>
    <h2>Sopa de tomate asado</h2>
    <p>Por Carlos, 20 minutos</p>
  </header>
  <p>Corta los tomates por la mitad y asalos hasta que estén blandos.</p>
  <footer>
    <p>Sirve para cuatro personas.</p>
  </footer>
</article>

Los siete elementos de región son los puntos de referencia de HTML: elementos que exponen una región navegable en el árbol de accesibilidad. Cada uno se asigna a un rol que la tecnología de asistencia puede enumerar y saltar entre ellos, que es la razón completa por la que importan más allá de verse organizados en el código fuente.

  • <header> se asigna 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 punto de referencia.
  • <footer> refleja eso: contentinfo a nivel de página, y un grupo plano cuando está anidado dentro de uno de esos elementos de sección.
  • <nav> es el rol navigation. Una página comúnmente tiene más de uno, un menú principal y una lista de contenidos en la página, que es donde entra el etiquetado abajo.
  • <main> es el rol main y marca el contenido principal. Hay uno por página.
  • <aside> es el rol complementary: contenido que apoya el contenido principal pero está separado de él.
  • <section> se convierte en un punto de referencia region solo cuando tiene un nombre accesible, normalmente de un encabezado vinculado a él; una <section> sin nombre no expone ningún punto de referencia y es, para el árbol de accesibilidad, cercana a un <div>.
  • <article> porta el rol article, una composición autocontenida, que las herramientas pueden enumerar pero que no es un punto de referencia de navegación en el mismo sentido que los otros.

El objetivo del diseño es un documento que un usuario no visual puede examinar tan rápido como un usuario vidente escanea el diseño. Un lector de pantalla puede producir una lista de cada punto de referencia y dejar que el usuario salte directamente a "main" o "navigation" sin escuchar el contenido intermedio. Eso solo funciona si las regiones se marcan con elementos de punto de referencia reales. Un documento lleno de <div>s produce un documento sin puntos de referencia en absoluto, por lo que la única forma de atravesarlo 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 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, aparecen una y otra vez hasta que se queden.
JunoLos elementos de referencia Siete elementos dividen una página en regiones, y la mayoría de ellos describen lo que sea que contengan, por lo que <header> y <footer> pueden aparecer más de una vez. La prueba de <article> que me ahorró mucha indecisión: ¿podría esto estar solo si lo sacas? Si sí, es un artículo; si es un fragmento agrupado con un encabezado, es una sección.
JunoLos elementos de referencia Estos son los puntos de referencia, y cada uno se asigna a un rol al que un lector de pantalla puede saltar, que es por qué vencen a un montón de <div>s. Dos cosas a tener en cuenta: <header> y <footer> solo se convierten en los puntos de referencia banner y contentinfo en el nivel superior, y una <section> es solo un punto de referencia una vez que tiene un nombre accesible. Una sección sin nombre es básicamente un div para la tecnología de asistencia.

div y span, la alternativa no semántica

No todas las partes de una página tienen un significado que valga la pena nombrar. A veces solo necesitas una caja para agrupar cosas para que puedas estilizarlas, o envolver algunas palabras para colorearlas. Para eso hay dos elementos planos sin significado propio.

<div> es un bloque genérico: un contenedor vacío que usas cuando ningún otro elemento se ajusta. <span> es la misma idea para una pequeña ejecución de texto dentro de una línea. Ninguno dice nada sobre su contenido. Existen puramente como enlaces para estilos y agrupaciones.

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

<div class="card">
  <h2>Oferta especial</h2>
  <p>Dos por uno en todas las pastas.</p>
</div>

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

<div> y <span> son los dos elementos sin ningún significado, y eso es exactamente para qué son. Un <div> es un contenedor genérico a nivel de bloque; un <span> es un contenedor genérico en línea. Los usas como enlaces de estilo: un lugar para poner una clase o una id cuando necesitas agrupar o apuntar a contenido pero no hay nada significativo que decir al respecto.

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

El <div class="grid"> existe solo para diseñar las tarjetas en una cuadrícula. Ese es un trabajo de presentación, no uno significativo, por lo que un <div> es la opción correcta, no una alternativa de la que deberías sentirte mal. El error es el inverso: usar un <div> para algo que sí tiene significado. Un <div> clickeable debería ser un <button>, un <div> lleno de enlaces de navegación debería ser una <nav>, un <div> que envuelve un post completo 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 e inline, respectivamente, sin rol en el árbol de accesibilidad y sin significado para ninguna herramienta. Son la opción correcta para un trabajo, un enlace de presentación: un elemento que existe solo para adjuntar estilos o para agrupar hijos para diseño, y que no porta información que un lector de pantalla o motor de búsqueda deba anunciar.

El valor de tener un elemento sin significado en absoluto es que mantiene los elementos significativos siendo verdaderos. Un envoltorio de cuadrícula, una fila flexbox, un contexto de posicionamiento: estas son necesidades reales sin contenido semántico, y forzar un elemento significativo sobre ellos sería una mentira en el marcado. Una <section> usada únicamente para un color de fondo afirma ser una región que no es. Entonces la regla corre de ambas formas. No recurras a un <div> cuando un elemento nombrado se ajusta, y no recurras a un elemento nombrado cuando todo lo que necesitas es una caja.

El modo de falla a tener cuidado es el <div> interactivo: un elemento al que se le da un manejador de clic en JavaScript para actuar como un botón o un enlace. Se renderiza y se hace clic con un ratón, así que se ve terminado, pero no tiene rol, no está en el orden de tabulación, no responde a Intro o 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 una cosa se comporta como un control, usa el elemento de control; mantén <div> y <span> para las partes que son solo píxeles.

Junodiv y span, la alternativa no semántica<div> es una caja plana y <span> es un envoltorio plano para algunas palabras, y ninguno de los dos significa nada. Úsalos cuando solo necesites agrupar o estilizar algo y ningún elemento nombrado se ajusta. Si la cosa sí tiene un significado, como un menú o un botón, usa el elemento para eso en su lugar.
Junodiv y span, la alternativa no semántica Un <div> o <span> es la opción correcta cuando el único trabajo es diseño o estilo, sin significado que establecer. No te sientas mal por ellos, siéntete mal por lo inverso: un <div> clickeable que debería ser un <button>, o un <div> envoltorio que debería ser un <article>. Elemento vacío para significado vacío, elemento nombrado para significado real.
Junodiv y span, la alternativa no semántica<div> y <span> no tienen rol en el árbol de accesibilidad, que es precisamente por qué son correctos para enlaces de estilo puro e incorrectos para cualquier cosa significativa. El que te morderá es el <div> interactivo con un manejador de clic: sin enfoque, sin teclado, sin anuncio, y un montón de parches tabindex y role para fingir lo que <button> te da por nada. Si se comporta como un control, hazlo el control.

Elegir el elemento correcto

Cuando no estés seguro de qué elemento usar, haz una pregunta simple: ¿qué es esto? No qué se ve como, sino qué es. La respuesta generalmente nombra el elemento para ti. Una fila de enlaces en la parte superior es navegación, así que es una <nav>. Un bloque de letra pequeña en la parte inferior es un pie de página, así que es un <footer>. Un precio que quieres colorear no es realmente nada, así que es un <span>.

Empieza por el significado, y solo recurre a un <div> o <span> cuando la respuesta real es "es solo una caja". Entrar en este hábito desde el principio significa que tus páginas se describen a sí mismas, y eso paga dividendos el momento en que tú o alguien más tiene que leer el marcado de nuevo.

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

  • ¿Es su propia cosa completa que tendría sentido por sí sola? <article>.
  • ¿Es un fragmento 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 el 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 complicada es <section> versus <article> versus <div>. Caminala en orden. Si el bloque podría estar solo, es un <article>. Si no pero es un grupo temático con su propio encabezado, es una <section>. Si no tiene encabezado y no tiene significado, y existe solo para ser estilizado o diseñado, es un <div>. Una <section> casi siempre debería tener un encabezado; si no puedes pensar en uno, eso es una fuerte pista de que querías un <div>.

html
<main>
  <section>
    <h2>Últimas entradas</h2>
    <article>
      <h3>Por qué cambié a HTML plano</h3>
      <p>...</p>
    </article>
    <article>
      <h3>El caso en contra de los marcos pesados</h3>
      <p>...</p>
    </article>
  </section>
</main>

Aquí la <section> es un grupo temático, "últimas entradas", y cada entrada dentro de ella es un <article> porque está por sí sola. El anidamiento refleja el significado.

Elegir bien se reduce a leer el significado primero y el diseño nunca, pero algunas reglas hacen que las decisiones comunes sean mecánicas.

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

La otra regla que importa repetidamente es etiquetar puntos de referencia repetidos. Cuando una página tiene dos elementos del mismo tipo de punto de referencia, una <nav> principal y una tabla de contenidos en la página, ambas anuncian como "navegación" y el usuario no puede diferenciarlas. Las desambigúas con aria-label, un atributo que proporciona un nombre accesible corto para una región sin mostrar nada en la 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 anuncian como "navegación principal" y "navegación en esta página", y la lista de puntos de referencia es utilizable. Aplica el mismo etiquetado a cualquier punto de referencia repetido, <aside> o <section> incluidos. Para <section>, recuerda que solo se convierte en un punto de referencia una vez que tiene un nombre accesible en absoluto, ya sea de un encabezado asociado o de un aria-label.

La metarregla 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 búsqueda, herramientas de modo de lectura, y tu yo futuro. Elegir elementos por significado es lo que hace que esa descripción sea verdadera. El diseño es trabajo de CSS, y cada vez que te encuentres eligiendo un elemento por cómo se ve, has entrado en el carril de CSS usando la herramienta equivocada.

JunoElegir el elemento correcto Cuando estés atrapado, pregúntate qué es la cosa, no qué se ve como. Navegación es una <nav>, letra pequeña es un <footer>, una caja plana que quieres estilizar es un <div>. Empieza por el significado cada vez, y tus páginas terminan describiéndose a sí mismas.
JunoElegir el elemento correcto Ejecuta la pequeña lista de verificación: está solo es un <article>, grupo temático con un encabezado es una <section>, sin significado y solo estilo es un <div>. El desempate que resuelve la mayoría de argumentos de section-versus-div: si no puedes pensar en un encabezado para ello, querías un <div>. Deja que el significado elija la etiqueta y el anidamiento se ordena por sí solo.
JunoElegir el elemento correcto Dos reglas cargan la mayoría del peso: exactamente uno <main> por página, y etiqueta puntos de referencia repetidos con aria-label para que dos navs no digan ambas "navegación". Ten en cuenta que una <section> es solo un punto de referencia una vez que tiene un nombre accesible. Elige elementos por significado y deja la apariencia a CSS, porque el momento en que eliges una etiqueta por cómo se renderiza, estás haciendo trabajo de CSS con la herramienta equivocada.