TechLead

Accesibilidad (a11y)

ARIA, lectores de pantalla y diseño inclusivo

¿Qué es la Accesibilidad Web?

La accesibilidad web (a11y—"a" + 11 letras + "y") asegura que las personas con discapacidades puedan usar tu sitio web. Esto incluye:

Visual

Ceguera, baja visión, daltonismo

Auditiva

Sordera o dificultad auditiva

Motora

Movilidad limitada, usuarios solo de teclado

Cognitiva

Discapacidades de aprendizaje, problemas de memoria

La accesibilidad beneficia a todos—usuarios móviles, personas mayores, personas con lesiones temporales, usuarios bajo luz solar intensa, etc.

HTML Semántico: La Base

Usar los elementos HTML correctos proporciona accesibilidad incorporada:

Inaccesible

<div onclick="submit()">
  Haz clic aquí
</div>

No accesible por teclado (sin foco con Tab)

Los lectores de pantalla no saben que es clicable

Sin soporte para tecla Enter

Accesible

<button onclick="submit()">
  Haz clic aquí
</button>

Accesible por teclado (Tab + Enter)

Los lectores de pantalla anuncian "Botón: Haz clic aquí"

Funciona con tecnología asistiva

Texto Alternativo para Imágenes

Esencial para usuarios de lectores de pantalla y cuando las imágenes no cargan.

Malo

<img src="perro.jpg" />

<img src="grafico.png" alt="imagen" />

<img src="logo.svg" alt="logo.svg" />

El lector de pantalla no dice nada o información inútil

Bueno

<img src="perro.jpg" alt="Golden retriever jugando a buscar" />

<img src="grafico.png" alt="Las ventas aumentaron 45% en Q4 2024" />

<!-- Imágenes decorativas -->
<img src="divisor.png" alt="" />

Descriptivo, contextual, o vacío para decorativas

Navegación por Teclado

Muchos usuarios navegan sin ratón. Asegura que todos los elementos interactivos sean accesibles por teclado.

Controles Clave del Teclado

Tab: Navegar hacia adelante por elementos interactivos
Shift + Tab: Navegar hacia atrás
Enter: Activar botones, enlaces
Espacio: Activar botones, alternar casillas
Teclas de flecha: Navegar radio buttons, desplegables
Esc: Cerrar modales, cancelar acciones

No accesible por teclado

<div onclick="mostrarMenu()">
  Menú
</div>

<span onclick="abrirModal()">
  Ver detalles
</span>

Accesible por teclado

<button onclick="mostrarMenu()">
  Menú
</button>

<button onclick="abrirModal()">
  Ver detalles
</button>

ARIA (Aplicaciones de Internet Ricas Accesibles)

Los atributos ARIA mejoran la accesibilidad cuando el HTML semántico no es suficiente.

Primera Regla de ARIA: ¡No uses ARIA a menos que tengas que hacerlo!

El HTML semántico es usualmente mejor. Usa ARIA solo cuando HTML solo no puede transmitir el significado.

aria-label

Proporciona nombre accesible cuando el texto visible no es suficiente:

<button aria-label="Cerrar diálogo">
  x
</button>

<button aria-label="Buscar">
  (icono de búsqueda)
</button>

<a href="/perfil" aria-label="Ver tu perfil">
  <img src="avatar.jpg" alt="" />
</a>

aria-labelledby y aria-describedby

Vincula elementos a sus etiquetas/descripciones:

<h2 id="titulo-dialogo">Confirmar eliminación</h2>
<p id="desc-dialogo">Esta acción no se puede deshacer.</p>
<div
  role="dialog"
  aria-labelledby="titulo-dialogo"
  aria-describedby="desc-dialogo"
>
  <!-- contenido del diálogo -->
</div>

aria-hidden

Oculta elementos decorativos de los lectores de pantalla:

<button>
  <span aria-hidden="true">*</span>
  Favorito
</button>

<!-- Iconos decorativos -->
<span class="icon" aria-hidden="true">-></span>

role

Define el propósito del elemento cuando el HTML semántico no está disponible:

<div role="button" tabindex="0">
  Botón personalizado
</div>

<div role="navigation">
  <!-- enlaces de navegación -->
</div>

<div role="alert">
  ¡Formulario enviado con éxito!
</div>

aria-live

Anuncia cambios de contenido dinámico:

<!-- Polite: espera a que el lector termine -->
<div aria-live="polite">
  3 artículos en el carrito
</div>

<!-- Assertive: interrumpe inmediatamente -->
<div aria-live="assertive" role="alert">
  Error: ¡El pago falló!
</div>

Gestión del Foco

Haz visibles los estados de foco y gestiona el flujo del foco:

Malo

/* Elimina el contorno de foco */
button:focus {
  outline: none;
}

Los usuarios de teclado no pueden ver dónde están

Bueno

/* Estilos de foco personalizados */
button:focus {
  outline: 2px solid blue;
  outline-offset: 2px;
}

/* O usa :focus-visible */
button:focus-visible {
  outline: 2px solid blue;
}

Indicador visual claro para usuarios de teclado

Errores Comunes de Accesibilidad

  • Usar divs/spans para botones: Usa <button> en su lugar
  • Falta de texto alt: Cada imagen necesita alt (incluso vacío para decorativas)
  • Contraste de color pobre: El texto debe ser legible (ratio mínimo 4.5:1)
  • Sin acceso por teclado: Todos los elementos interactivos deben ser accesibles por teclado
  • Eliminar contornos de foco: No uses outline: none sin estilos de foco personalizados
  • Reproducción automática de medios: No reproduzcas videos/audio automáticamente sin controles
  • Inputs de formulario sin labels: Cada input necesita un <label>

Lista de Verificación de Accesibilidad

  • Usa HTML semántico: <button>, <nav>, <main>, etc.
  • Proporciona texto alt: Descriptivo para imágenes significativas, vacío para decorativas
  • Asegura navegación por teclado: Prueba solo con la tecla Tab
  • Mantén contraste de color: Usa verificadores de contraste en línea
  • Etiqueta todos los inputs: Usa <label for="id">
  • Usa ARIA con moderación: Solo cuando el HTML semántico no es suficiente
  • Proporciona enlaces de salto: "Saltar al contenido principal" para usuarios de teclado
  • Prueba con lectores de pantalla: NVDA (Windows), VoiceOver (Mac), JAWS
  • Usa jerarquía de encabezados: h1, h2, h3 (no saltes niveles)

Herramientas de Prueba

  • Lighthouse: Integrado en Chrome DevTools, audita accesibilidad
  • WAVE: Extensión de navegador para evaluación visual de accesibilidad
  • axe DevTools: Pruebas de accesibilidad completas
  • Prueba de teclado: Navega tu sitio usando solo Tab, Enter, Espacio, teclas de flecha
  • Lectores de pantalla: NVDA (gratis, Windows), VoiceOver (Mac), JAWS (Windows)
  • Verificador de contraste: WebAIM Contrast Checker