♿ A11Y — Ingeniería de Accesibilidad Web & Estándar WCAG 2.2

Dominio Técnico de Accesibilidad Universal (W3C WAI & EN 301 549)

A11Y es el numerónimo técnico de accessibility (la letra A inicial, 11 letras intermedias y la Y final). En ingeniería de software moderna, la accesibilidad garantiza que cualquier persona —incluyendo usuarios con discapacidades visuales, auditivas, motoras, neurológicas o cognitivas— pueda percibir, comprender, navegar e interactuar con una interfaz web mediante lectores de pantalla (NVDA, VoiceOver, JAWS), navegación por teclado o conmutadores físicos.

  • 📜 Normativa Vigente: W3C WCAG 2.2 (Recomendación Oficial) + European Accessibility Act (EAA 2025/2026 — EN 301 549 v4.1.1)
  • 🛠️ Ecosistema de Auditoría: Pa11y CLI · Google Lighthouse 12 · axe-core · Chrome DevTools Accessibility Tree

🧭 Los 4 Principios Fundamentales (POUR)

Todo sistema accesible se sostiene sobre los cuatro pilares POUR del W3C:

flowchart LR
    A11Y(["♿ Accesibilidad Web\n(WCAG 2.2 AA/AAA)"]) --> P["👁️ 1. Perceptible\n(Alternativas textuales, subtítulos,\ncontraste ≥ 4.5:1, adaptable)"]
    A11Y --> O["⌨️ 2. Operable\n(100% Teclado, sin trampas de foco,\ntargets ≥ 24x24px, sin parpadeos)"]
    A11Y --> U["🧠 3. Comprensible\n(Idioma declarado, navegación predecible,\nayuda en errores y login sin fricción)"]
    A11Y --> R["⚙️ 4. Robusto\n(HTML5 semántico, roles ARIA válidos,\ncompatibilidad con Accessibility Tree)"]
PrincipioObjetivo TécnicoRegla de Oro en Código
1. PerceptibleLa información no puede ser invisible para todos los sentidos del usuario.Todo <img> requiere alt descriptivo (o alt="" si es decorativo); contraste mínimo 4.5:1 (AA).
2. OperableLos componentes de interfaz y la navegación deben ser ejecutables sin ratón.Todo flujo interactivo debe funcionar con Tab, Shift + Tab, Enter, Space y Esc.
3. ComprensibleLa información y el manejo de la UI no deben exigir carga cognitiva innecesaria.Definir <html lang="es">, asociar cada <input> con su <label> y evitar bloqueos al pegar contraseñas.
4. RobustoEl contenido debe ser interpretado de forma fiable por tecnologías de asistencia.Priorizar HTML nativo (<button>, <dialog>, <nav>) antes de inventar <div> con ARIA.

⚡ Novedades Críticas en WCAG 2.2 (Los 9 Nuevos Criterios)

WCAG 2.2 elimina el antiguo criterio 4.1.1 Parsing (ya que los navegadores modernos construyen el árbol DOM de forma estandarizada) e introduce 9 criterios clave:

CriterioNombre OficialNivelImpacto en Diseño & Frontend
2.4.11Focus Not Obscured (Min)AACuando un elemento recibe foco con Tab, no puede quedar tapado por sticky headers, banners de cookies o footers flotantes.
2.4.12Focus Not Obscured (Enh)AAANinguna fracción del elemento enfocado puede quedar cubierta por capas superpuestas.
2.4.13Focus AppearanceAAAEl anillo de foco (:focus-visible) debe tener al menos 2px de grosor y contraste 3:1 entre estado enfocado y no enfocado.
2.5.7Dragging MovementsAATodo drag-and-drop (como tableros Kanban o sliders) debe ofrecer botones alternativos de clic simple para mover elementos.
2.5.8Target Size (Minimum)AALas áreas táctiles o clicables deben medir mínimo 24×24 CSS px (recomendado 48×48 px en móvil según web.dev).
3.2.6Consistent HelpALos enlaces de soporte, chat o contacto deben ubicarse siempre en la misma posición relativa en todas las páginas.
3.3.7Redundant EntryAProhibido obligar al usuario a volver a escribir datos ya ingresados en el mismo flujo (ej. dirección de envío = facturación).
3.3.8Accessible AuthenticationAAProhibido bloquear el autocompletado o pegado (Ctrl + V) en campos de contraseña; permitir gestores de claves, Passkeys o enlaces mágicos.
3.3.9Accessible Auth (Enhanced)AAAElimina incluso los CAPTCHAs de reconocimiento de objetos visuales (“selecciona los semáforos”).

🌳 DOM Tree vs. Accessibility Tree (AOM)

El navegador convierte el DOM en el Accessibility Tree, que es la estructura real que consumen los lectores de pantalla:

Las 5 Reglas de WAI-ARIA y Ocultamiento Semántico

  1. Primera Regla de ARIA: Si puedes usar un elemento HTML5 nativo (<button>, <details>, <main>, <aside>) que ya tiene la semántica y el comportamiento de teclado que necesitas, NO uses un <div> con role="...".
  2. Diferencia al ocultar elementos:
    • opacity: 0 o visibility: visible fuera de pantalla: Sigue siendo leíble/enfocable si no se gestiona, creando focos fantasma.
    • display: none o visibility: hidden o atributo HTML hidden: Oculta tanto visualmente como del Accessibility Tree.
    • aria-hidden="true": Oculta el elemento del lector de pantalla pero lo mantiene visible en pantalla (ideal para iconos SVG puramente decorativos). Nunca apliques aria-hidden="true" a un elemento enfocable con teclado.
    • .sr-only (clip-path: inset(50%)): Oculta visualmente pero lo deja 100% disponible para lectores de pantalla.

🎨 Contraste de Color: Matemática WCAG 2.x vs. APCA (WCAG 3.0)

Tipo de ElementoNivel AA (Estándar Legal)Nivel AAA (Excelencia)Notas de Implementación
Texto Normal (< 18pt o < 14pt bold)4.5 : 17.0 : 1Calculado por luminancia relativa tradicional.
Texto Grande (≥ 18pt / 24px o ≥ 14pt / 18.66px bold)3.0 : 14.5 : 1Títulos H1/H2 y encabezados destacados.
Componentes UI & Gráficos (Bordes de inputs, iconos, estados de foco)3.0 : 14.5 : 1Criterio 1.4.11 Non-text Contrast.

¿Qué es APCA (Advanced Perceptual Contrast Algorithm)?

Mientras que WCAG 2.2 evalúa proporciones matemáticas planas (4.5:1), el borrador de WCAG 3.0 introduce APCA, un modelo perceptual que mide la legibilidad en valores de luminancia perceptual ( de 0 a 106) considerando el grosor de la fuente (font-weight), el tamaño y la polaridad (modo oscuro vs. modo claro). Para cumplimiento normativo actual (EAA / ADA / Sección 508), WCAG 2.2 AA sigue siendo el requisito legal obligatorio.


💻 Patrones de Código Accesible (HTML5 + CSS Brutalista)

Plantilla de Navegación, Foco Visible y Modal Accesible

<!-- 1. Skip Link (Salto directo al contenido principal para usuarios de teclado) -->
<a href="#main-content" class="sr-only focus:not-sr-only">
  Saltar al contenido principal
</a>
 
<!-- 2. Botón con Icono Decorativo (Nombre Accesible explícito) -->
<button type="button" aria-label="Cerrar ventana modal">
  <svg aria-hidden="true" focusable="false" width="24" height="24">...</svg>
</button>
 
<!-- 3. Región Viva para Notificaciones Dinámicas (Toasts / Alertas) -->
<div role="status" aria-live="polite" aria-atomic="true">
  Cambios guardados correctamente en la bóveda.
</div>
/* Anillo de foco de alto contraste acorde a WCAG 2.4.13 y Scorch Design */
:focus-visible {
  outline: 2px dashed #E63946 !important;
  outline-offset: 4px !important;
}
 
/* Respetar preferencia de reducción de movimiento vestibular (WCAG 2.3.3) */
@media (prefers-reduced-motion: reduce) {
  *, ::before, ::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

🔍 Flujo de Auditoría y Debugging en Proyectos Reales

  1. Auditoría Automatizada (~40-50% de problemas detectables):
    • Ejecutar Pa11y con los motores axe y htmlcs en CI/CD.
    • Ejecutar Google Lighthouse en modo navegación para validar nombres accesibles, orden de encabezados (h1 → h2 → h3 sin saltos) y contrastes.
  2. Inspección Manual con Teclado (Obligatoria):
    • Desconectar el ratón y recorrer toda la página con Tab.
    • Comprobar que los modales atrapan el foco (focus trap) mientras están abiertos y devuelven el foco al botón disparador al cerrarse con Esc.
  3. Verificación del Accessibility Tree en Chrome DevTools:
    • Abrir DevTools → Pestaña Elements → Sub-pestaña Accessibility → Inspeccionar el nombre computado (Computed Properties) y los roles expuestos al sistema operativo.

🔗 Conexiones en la Bóveda