Addaw, ir a inicio Donar

Lección 5 de 10 · 12 min de lectura · Revisado el 26/10/2026

ARIA 1.3, HTML nuevo y CSS moderno para la accesibilidad

La plataforma web ha incorporado en los últimos años capacidades nativas que resuelven problemas de accesibilidad que antes exigían bibliotecas y mucho ARIA: diálogos modales, popovers, inertización de contenido, estilos de foco inteligentes y consultas de preferencias del usuario. A la vez, WAI-ARIA (se abre en una ventana nueva) evoluciona con la versión 1.3. Esta lección repasa lo que ya se puede usar con seguridad, lo que exige cautela por compatibilidad y las implicaciones de accesibilidad de cada novedad, con ejemplos de código.

WAI-ARIA 1.3: qué añade

WAI-ARIA 1.2 es la recomendación vigente (junio de 2023) y WAI-ARIA 1.3 es un borrador de trabajo del W3C. Las incorporaciones más relevantes del borrador, con soporte creciente en navegadores y tecnologías de apoyo, son:

  • aria-description: permite dar una descripción accesible con texto directo, sin necesidad de un elemento referenciado por aria-describedby. Útil para componentes generados dinámicamente. Preferir siempre texto visible referenciado cuando exista.
  • aria-braillelabel y aria-brailleroledescription: permiten ofrecer una etiqueta o descripción de rol específicas para líneas braille (más cortas o con abreviaturas braille). Solo deben usarse cuando la salida braille mejora respecto a la etiqueta normal; mal usados, empeoran la experiencia.
  • Roles de anotación (comment, suggestion, mark) para comentarios y cambios propuestos en editores de documentos colaborativos, un caso de uso frecuente sin semántica hasta ahora.
  • Clarificaciones y nuevas restricciones sobre combinaciones de roles y propiedades, además de mejoras en el cálculo del nombre accesible.

Cautelas: comprueba el soporte real en la combinación de navegador y lector de pantalla de tus usuarios antes de depender de una propiedad nueva, y recuerda la primera regla de ARIA: si HTML nativo lo resuelve, no uses ARIA.

HTML: lo nativo que ya puedes usar

<dialog>

El elemento <dialog> con showModal() resuelve de forma nativa lo que antes exigía gestionar a mano: modalidad (el resto de la página queda inerte), foco inicial dentro del diálogo, cierre con Esc y devolución del foco al elemento que lo abrió. Tiene soporte en todos los navegadores actuales.

<button type="button" id="abrir">Eliminar cuenta</button>

<dialog id="confirmar" aria-labelledby="titulo-confirmar">
  <h2 id="titulo-confirmar">¿Eliminar la cuenta?</h2>
  <p>Esta acción no se puede deshacer.</p>
  <form method="dialog">
    <button value="cancelar" autofocus>Cancelar</button>
    <button value="eliminar">Eliminar</button>
  </form>
</dialog>

<script>
  const d = document.getElementById('confirmar');
  document.getElementById('abrir').addEventListener('click', () => d.showModal());
</script>

Buenas prácticas: usa showModal() (no show() ni el atributo open directamente, que no hacen el diálogo modal); da nombre accesible con aria-labelledby; coloca el foco inicial en el control menos destructivo con autofocus; verifica que el fondo (::backdrop) cumple contraste y que el diálogo responde al zoom y al reajuste.

Atributo popover

El atributo popover crea contenido superpuesto no modal (menús, sugerencias, avisos, selectores) con gestión de capa superior, cierre con Esc o al pulsar fuera (popover="auto") y conexión declarativa con su botón mediante popovertarget. Tiene soporte en los navegadores principales desde 2024.

<button type="button" popovertarget="ayuda-dni">
  Ayuda sobre el formato del DNI
</button>
<div id="ayuda-dni" popover role="note">
  Escribe ocho cifras y la letra, sin espacios ni guiones.
</div>

Cautelas: popover no aporta semántica por sí mismo; añade el rol adecuado (menu, listbox, dialog no modal, note…), comprueba que el botón expone su estado expandido (los navegadores actuales lo derivan de popovertarget; si añades aria-expanded a mano, mantenlo sincronizado) y asegúrate de que el contenido es alcanzable con teclado y legible con lector de pantalla. Un popover de tipo tooltip sigue debiendo cumplir 1.4.13 Contenido con hover o foco (descartable, señalable, persistente).

Atributo inert

inert hace que un subárbol sea no interactivo e invisible para las tecnologías de apoyo: no recibe foco, no se puede pulsar y se excluye del árbol de accesibilidad. Es la forma correcta de «apagar» el resto de la página cuando hay un diálogo personalizado abierto (si no usas <dialog>) o un panel lateral. Cuidado: no es ocultación visual; combínalo con estilos si procede, y no lo olvides activo.

Elemento <search>

Equivale al landmark role="search" de forma nativa: envuelve el formulario de búsqueda para que las personas usuarias de lector de pantalla salten directamente a él.

CSS moderno al servicio de la accesibilidad

:focus-visible

Permite mostrar el indicador de foco solo cuando el navegador determina que es útil (navegación con teclado), evitando que el equipo de diseño elimine el outline por aparecer tras un clic de ratón. Es la base del anillo de foco de cualquier design system y la forma correcta de cumplir 2.4.7 Foco visible sin molestar a quien usa ratón. Nunca uses outline: none sin una alternativa visible en :focus-visible.

:focus { outline: none; }            /* incorrecto si se deja así */

:focus-visible {                      /* correcto */
  outline: 3px solid #1a1a1a;   /* ≥ 3:1 sobre el fondo */
  outline-offset: 2px;
}

Consultas de preferencias (prefers-*)

  • prefers-reduced-motion: reduce: desactiva o minimiza animaciones y desplazamientos automáticos; relacionado con 2.3.3 Animación a partir de interacciones (AAA) y con la buena práctica para 2.2.2.
  • prefers-contrast: more: aumenta contrastes y grosores de borde para quien lo ha pedido en su sistema.
  • prefers-color-scheme: dark: modo oscuro; recuerda verificar el contraste también en la paleta oscura (1.4.3, 1.4.11).
  • prefers-reduced-transparency: reduce transparencias que dificultan la lectura.

forced-colors y colores del sistema

En el modo de colores forzados (por ejemplo, el alto contraste de Windows), el navegador sustituye los colores por la paleta del sistema. La consulta @media (forced-colors: active) permite ajustar lo que se rompe (iconos SVG que desaparecen, bordes que se pierden, foco invisible) usando las palabras clave de color del sistema (CanvasText, Highlight, ButtonText) en lugar de colores fijos.

@media (forced-colors: active) {
  .icono { forced-color-adjust: none; fill: CanvasText; }
  .boton-seleccionado { outline: 2px solid Highlight; }
}

Otras utilidades

  • :has() permite estilizar un contenedor según su contenido (por ejemplo, resaltar un grupo de campos que contiene un error) sin JavaScript ni clases adicionales.
  • Las consultas de contenedor (@container) ayudan a que los componentes se adapten al espacio disponible y faciliten el reajuste a 320 píxeles (1.4.10).
  • text-wrap: balance y text-wrap: pretty mejoran la legibilidad de titulares y párrafos sin afectar a la estructura.
  • Unidades relativas (rem, em) y clamp() para tipografía fluida que respeta el tamaño de texto del usuario (1.4.4).

Punto clave

Cada capacidad nativa que adoptas (dialog, popover, inert, search, focus-visible) elimina código propio y ARIA que podía estar mal; pero ninguna te exime de probar con teclado y lector de pantalla, porque la semántica (roles, nombres, estados) sigue siendo tu responsabilidad.

Error frecuente

Migrar un menú desplegable a popover y considerarlo accesible porque «es nativo». El atributo gestiona la capa y el cierre, pero el botón debe exponer su estado expandido (compruébalo y, si usas aria-expanded, mantenlo sincronizado), el contenido necesita su rol y su navegación con teclado (flechas en un menú), y el conjunto una prueba con lector de pantalla. Nativo no significa semántico.

Lista de comprobación de adopción

  1. Consulta el soporte actual de cada característica en la documentación de referencia (por ejemplo, MDN sobre popover) y en tus datos de navegadores.
  2. Sustituye diálogos personalizados por <dialog> con showModal() y nombre accesible.
  3. Usa popover para capas no modales, añadiendo rol, estado expandido comprobado y teclado.
  4. Usa inert para desactivar regiones cuando no uses <dialog>.
  5. Define el anillo de foco en :focus-visible en el design system.
  6. Implementa prefers-reduced-motion, prefers-contrast y forced-colors y pruébalos activando las preferencias del sistema.
  7. Verifica cada novedad con teclado, NVDA y VoiceOver antes de generalizarla.

Resumen

  • WAI-ARIA 1.3 (borrador) añade aria-description, propiedades braille y roles de anotación; usa ARIA solo cuando HTML nativo no baste y comprueba el soporte.
  • <dialog> con showModal(), popover, inert y <search> resuelven de forma nativa modalidad, capas, desactivación de regiones y landmark de búsqueda.
  • :focus-visible, prefers-reduced-motion, prefers-contrast, prefers-color-scheme y forced-colors permiten respetar las preferencias del usuario y cumplir 2.4.7, 2.3.3 y los criterios de contraste en todos los modos.
  • Nativo no significa semántico: la responsabilidad de roles, nombres, estados y pruebas sigue siendo del equipo.

Comprueba lo que has aprendido

Esta lección se puede leer libremente. Para hacer su test de 3 preguntas, los ejercicios prácticos con páginas reales, guardar tu avance y optar al examen y al certificado, matricúlate en el curso.

Matricularme · nivel 7 (179 €)