♿ 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)
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)"]
Principio
Objetivo Técnico
Regla de Oro en Código
1. Perceptible
La 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. Operable
Los 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. Comprensible
La 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. Robusto
El 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:
Criterio
Nombre Oficial
Nivel
Impacto en Diseño & Frontend
2.4.11
Focus Not Obscured (Min)
AA
Cuando un elemento recibe foco con Tab, no puede quedar tapado por sticky headers, banners de cookies o footers flotantes.
2.4.12
Focus Not Obscured (Enh)
AAA
Ninguna fracción del elemento enfocado puede quedar cubierta por capas superpuestas.
2.4.13
Focus Appearance
AAA
El anillo de foco (:focus-visible) debe tener al menos 2px de grosor y contraste 3:1 entre estado enfocado y no enfocado.
2.5.7
Dragging Movements
AA
Todo drag-and-drop (como tableros Kanban o sliders) debe ofrecer botones alternativos de clic simple para mover elementos.
2.5.8
Target Size (Minimum)
AA
Las á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.6
Consistent Help
A
Los enlaces de soporte, chat o contacto deben ubicarse siempre en la misma posición relativa en todas las páginas.
3.3.7
Redundant Entry
A
Prohibido obligar al usuario a volver a escribir datos ya ingresados en el mismo flujo (ej. dirección de envío = facturación).
3.3.8
Accessible Authentication
AA
Prohibido bloquear el autocompletado o pegado (Ctrl + V) en campos de contraseña; permitir gestores de claves, Passkeys o enlaces mágicos.
3.3.9
Accessible Auth (Enhanced)
AAA
Elimina 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
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="...".
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 Elemento
Nivel AA (Estándar Legal)
Nivel AAA (Excelencia)
Notas de Implementación
Texto Normal (< 18pt o < 14pt bold)
4.5 : 1
7.0 : 1
Calculado por luminancia relativa tradicional.
Texto Grande (≥ 18pt / 24px o ≥ 14pt / 18.66px bold)
3.0 : 1
4.5 : 1
Títulos H1/H2 y encabezados destacados.
Componentes UI & Gráficos (Bordes de inputs, iconos, estados de foco)
3.0 : 1
4.5 : 1
Criterio 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 (Lc 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
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.
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.
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.