Saltar al contenido
schedule 12 min HTML

Semántica y accesibilidad

Hasta ahora has construido páginas con <div> y etiquetas genéricas. Funcionan, pero el navegador, Google y los lectores de pantalla no saben qué es cada cosa. ¿Es un menú? ¿Un artículo? ¿El pie de página? Con HTML semántico, tu código se explica solo.

¿Qué es HTML semántico?

HTML semántico significa usar etiquetas que describen el significado del contenido, no solo su apariencia. Compara estos dos bloques:

no-semantico.html
<!-- Sin semántica: todo es div -->
<div class="header">
    <div class="nav">
        <div class="nav-item">Inicio</div>
        <div class="nav-item">Blog</div>
    </div>
</div>
<div class="main">
    <div class="article">
        <div class="title">Título del post</div>
        <div class="content">Contenido...</div>
    </div>
</div>
<div class="footer">
    <div class="copyright">© 2026</div>
</div>
semantico.html
<!-- Con semántica: cada etiqueta tiene significado -->
<header>
    <nav>
        <a href="/">Inicio</a>
        <a href="/blog">Blog</a>
    </nav>
</header>
<main>
    <article>
        <h1>Título del post</h1>
        <p>Contenido...</p>
    </article>
</main>
<footer>
    <p>© 2026</p>
</footer>

Visualmente pueden verse igual. Pero el segundo le dice al navegador, a Google y a los lectores de pantalla exactamente qué es cada bloque.

Las etiquetas semánticas de HTML5

Etiqueta Cuándo usarla
<header> Cabecera de la página o de una sección. Logo, título, navegación principal.
<nav> Bloque de navegación principal. Menús, breadcrumbs, paginación.
<main> El contenido principal de la página. Solo uno por página.
<article> Contenido independiente: un post de blog, un comentario, un producto.
<section> Sección temática del contenido. Agrupa contenido relacionado.
<aside> Contenido complementario: sidebar, widgets, info relacionada.
<footer> Pie de página o de sección. Copyright, enlaces legales, contacto.
<search> Bloque de búsqueda. Nuevo en HTML, más semántico que <form role="search">.

Estructura semántica de una web real

blog.html
<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PixelBlog — Diseño y desarrollo web</title>
</head>
<body>
    <header>
        <a href="/">PixelBlog</a>
        <nav aria-label="Navegación principal">
            <ul>
                <li><a href="/">Inicio</a></li>
                <li><a href="/articulos">Artículos</a></li>
                <li><a href="/sobre-mi">Sobre mí</a></li>
            </ul>
        </nav>
        <search>
            <form action="/buscar" method="GET">
                <label for="buscar" class="sr-only">Buscar artículos</label>
                <input type="search" id="buscar" name="q"
                       placeholder="Buscar...">
                <button type="submit">Buscar</button>
            </form>
        </search>
    </header>

    <main>
        <section aria-labelledby="ultimos-posts">
            <h1 id="ultimos-posts">Últimos artículos</h1>

            <article>
                <header>
                    <h2>Cómo optimizar imágenes para la web en 2026</h2>
                    <time datetime="2026-03-10">10 de marzo de 2026</time>
                </header>
                <p>Las imágenes representan el 50% del peso de la mayoría
                de webs. Aquí tienes 5 técnicas para reducirlas sin perder calidad...</p>
                <footer>
                    <p>Escrito por <a href="/autor/elena">Elena Martínez</a>
                    en <a href="/categoria/rendimiento">Rendimiento</a></p>
                </footer>
            </article>

            <article>
                <header>
                    <h2>Container queries: adiós a los media queries</h2>
                    <time datetime="2026-03-05">5 de marzo de 2026</time>
                </header>
                <p>Los container queries llevan años prometiendo cambiar
                cómo hacemos responsive design. En 2026, ya son la norma...</p>
                <footer>
                    <p>Escrito por <a href="/autor/elena">Elena Martínez</a>
                    en <a href="/categoria/css">CSS</a></p>
                </footer>
            </article>
        </section>
    </main>

    <aside aria-label="Barra lateral">
        <section>
            <h2>Categorías</h2>
            <ul>
                <li><a href="/categoria/css">CSS (12)</a></li>
                <li><a href="/categoria/javascript">JavaScript (8)</a></li>
                <li><a href="/categoria/rendimiento">Rendimiento (5)</a></li>
            </ul>
        </section>
    </aside>

    <footer>
        <p>© 2026 PixelBlog. Hecho con HTML, CSS y café.</p>
        <nav aria-label="Enlaces legales">
            <a href="/privacidad">Política de privacidad</a>
            <a href="/cookies">Cookies</a>
        </nav>
    </footer>
</body>
</html>

Etiquetas interactivas modernas

HTML tiene etiquetas que resuelven patrones de UI sin necesidad de JavaScript:

<details> y <summary>: acordeones nativos

<details>
    <summary>¿Puedo cancelar mi suscripción en cualquier momento?</summary>
    <p>Sí, puedes cancelar cuando quieras desde tu panel de usuario.
    Tu acceso se mantiene hasta que termine el periodo pagado.</p>
</details>

<details>
    <summary>¿Hay descuento para estudiantes?</summary>
    <p>Sí, ofrecemos un 50% de descuento con email universitario válido.
    Escríbenos a [email protected].</p>
</details>

<!-- Abierto por defecto -->
<details open>
    <summary>¿Qué métodos de pago aceptáis?</summary>
    <p>Tarjeta de crédito/débito, PayPal y transferencia bancaria.</p>
</details>

Cero JavaScript. El navegador gestiona abrir y cerrar cada bloque de forma nativa.

<dialog>: modales nativos

<button onclick="document.getElementById('modal-confirmar').showModal()">
    Eliminar cuenta
</button>

<dialog id="modal-confirmar">
    <h2>¿Estás seguro?</h2>
    <p>Esta acción no se puede deshacer. Todos tus datos se eliminarán.</p>
    <form method="dialog">
        <button value="cancel">Cancelar</button>
        <button value="confirm">Sí, eliminar</button>
    </form>
</dialog>

<dialog> con .showModal() crea un modal accesible de verdad: bloquea el foco dentro del modal, añade un fondo oscuro (::backdrop) y se cierra con Escape. Todo nativo.

Accesibilidad: ARIA básico

ARIA (Accessible Rich Internet Applications) son atributos que mejoran la accesibilidad cuando el HTML semántico no es suficiente:

<!-- aria-label: nombre invisible para lectores de pantalla -->
<button aria-label="Cerrar menú">
    <span>✕</span>
</button>

<!-- aria-labelledby: usa otro elemento como nombre -->
<section aria-labelledby="titulo-precios">
    <h2 id="titulo-precios">Nuestros precios</h2>
    <!-- contenido -->
</section>

<!-- aria-hidden: oculta elementos decorativos -->
<a href="/inicio">
    <span aria-hidden="true">🏠</span>
    Inicio
</a>

<!-- role: define la función del elemento -->
<div role="alert">Tu formulario se ha enviado correctamente.</div>

<!-- sr-only: solo visible para lectores de pantalla (con CSS) -->
<label for="buscar" class="sr-only">Buscar en el sitio</label>

La primera regla de ARIA: si puedes resolver algo con HTML semántico, no uses ARIA. Usa <button> en lugar de <div role="button">. Usa <nav> en lugar de <div role="navigation">. ARIA es el plan B.

Checklist de accesibilidad básica

  • Todas las imágenes tienen alt descriptivo (excepto las decorativas, que llevan alt="").
  • Todos los campos de formulario tienen <label>.
  • Los encabezados siguen una jerarquía lógica (h1 → h2 → h3).
  • Los enlaces tienen texto descriptivo (no "clic aquí").
  • La página se puede navegar solo con teclado (Tab, Enter, Escape).
  • Los colores tienen contraste suficiente (ratio mínimo 4.5:1).
  • El idioma está declarado con lang.
  • Las navegaciones tienen aria-label cuando hay más de una.
code

Reestructura con HTML semántico

Medio schedule 15 min

Crea un archivo semantico.html con la estructura de un blog que incluya:

  • <header> con logo y <nav>
  • <main> con al menos 2 <article>
  • Cada artículo con su propio <header>, <time> y <footer>
  • <aside> con categorías y un buscador usando <search>
  • <footer> con navegación legal y copyright
  • Una sección de FAQ usando <details> y <summary> (mínimo 3 preguntas)
  • aria-label en las navegaciones
lightbulb Pistas

Usa el ejemplo de PixelBlog como referencia. Recuerda: solo un <main> por página. Cada <nav> debe tener un aria-label diferente para distinguirlas.

Newsletter

Recibe nuevos cursos, actualizaciones, artículos del blog y promociones en tu correo.