Product Craft Bible
Focus management en flujos complejos
Inicio Accesibilidad Focus management en flujos complejos
Accesibilidad

Focus management en flujos complejos

8 reglas WAI-ARIA APG Dialog (Modal) Pattern · WCAG 2.1.2 No Keyboard Trap (Nivel A)WAI-ARIA APG Dialog (Modal) Pattern · VA.gov Design System · Focus ManagementVA.gov Design System · Deque · WCAG 2.4.3 Focus Order · WCAG 2.4.2 Page TitledVA.gov Design System · Focus Management · WCAG 2.4.3 Focus Order (Nivel A)
24

Focus management en flujos complejos

8 reglas
245

Al abrir un modal, mueve el foco dentro y atrapalo hasta que se cierre

Cuando un dialogo modal se abre, el foco del teclado debe moverse de inmediato a un elemento dentro del dialogo, según el WAI-ARIA APG Dialog Pattern. Mientras el modal este abierto, Tab y Shift+Tab deben ciclar unicamente dentro de el: al llegar al último elemento, Tab vuelve al primero, y viceversa. Ningun elemento del fondo debe ser alcanzable con teclado. WCAG 2.1.2 prohibe las trampas de foco, pero exime explicitamente a los modales siempre que el usuario pueda salir con Escape u otro método conocido.

WAI-ARIA APG Dialog (Modal) Pattern · WCAG 2.1.2 No Keyboard Trap (Nivel A)
Preferir
Editar perfil
Foco al primer input, Tab cicla dentro
Evitar
Editar perfil
Tab navega el fondo bajo el overlay
246

Al cerrar un modal, devuelve el foco al elemento que lo disparo

Cuando un modal se cierra, el foco debe volver al elemento que lo abrio. Esto preserva el contexto espacial del usuario de teclado: sabe exactamente donde estaba en la página. El patrón es guardar el disparador antes de abrir (const trigger = document.activeElement) y al cerrar invocar trigger.focus(). El APG lo norma verbatim: el foco regresa al elemento que invoco el dialogo salvo que ya no exista o que el flujo sugiera un destino mejor. Si dejas el foco en body, el usuario reinicia la navegación desde el principio de la página.

WAI-ARIA APG Dialog (Modal) Pattern · VA.gov Design System · Focus Management
Preferir
trigger.focus()
foco vuelve al disparador
Evitar
cerrar
foco perdido en <body>
247

En SPAs, mueve el foco al heading de la vista y anuncia el cambio de ruta

Las Single Page Applications no disparan el comportamiento nativo del navegador al cambiar de ruta: ni scroll al inicio ni anuncio por lector de pantalla. El desarrollador debe gestionarlo a mano. El destino recomendado es el primer heading único de la nueva vista (con tabindex="-1" para poder enfocarlo); si no existe, el elemento que provea más contexto. Además document.title debe actualizarse para que el lector anuncie la página. Si el foco se queda en el link de navegación, el usuario de teclado no sabe que el contenido cambio.

VA.gov Design System · Deque · WCAG 2.4.3 Focus Order · WCAG 2.4.2 Page Titled
Preferir
Inicio Productos Ayuda
Productos
foco al heading, title "Productos"
Evitar
Inicio Productos Ayuda
Productos
foco atorado en el link, sin anuncio
248

Contenido dinámico: mueve el foco o usa live region según urgencia

Al insertar contenido nuevo en el DOM hay dos estrategias validas: mover el foco al contenido (cuando requiere acción o atención inmediata, como un resumen de errores o el siguiente paso de un wizard) o usar una region aria-live (cuando es informativo y no debe interrumpir). Nunca muevas el foco a un spinner de carga: anuncia el estado con ARIA y redirige el foco al contenido final cuando llegue. Evita combinar foco y aria-live en el mismo elemento, porque produce lecturas duplicadas. La elección depende de si el usuario debe actuar ya o solo enterarse.

VA.gov Design System · Focus Management · WCAG 2.4.3 Focus Order (Nivel A)
Preferir
Revisa los campos marcados
foco al resumen, campo con aria-invalid
Evitar
Revisa los campos marcados
foco sigue en Enviar, error ignorado
249

Nunca muevas el foco ni cambies de contexto solo por recibir foco

Recibir foco en un elemento no debe, por si solo, desencadenar un cambio de contexto: no abrir ventanas nuevas, no enviar formularios, no redirigir la URL ni mover el foco a otro componente. WCAG 3.2.1 On Focus (Nivel A) lo prohibe de forma absoluta y cualitativa: cero cambios de contexto disparados unicamente por el foco. Estos saltos inesperados desorientan a usuarios de teclado, lectores de pantalla y personas con discapacidades cognitivas. El cambio solo debe ocurrir tras una acción explicita: click, Enter o activación del control.

WCAG 3.2.1 On Focus (Nivel A)
Preferir
Pais
el foco no dispara cambios de contexto
Evitar
Pais
Idioma: Español
Idioma: English
onFocus abre panel y roba el foco
250

El orden de tabulación sigue el flujo lógico del DOM y el visual

Los componentes focusables deben recibir foco en un orden que preserve significado y operabilidad: el orden de lectura del DOM debe coincidir con el orden visual percibido. WCAG 2.4.3 Focus Order (Nivel A) lo exige cuando la secuencia de navegación afecta el significado. El antipatron documentado es usar tabindex con valores positivos para reordenar arbitrariamente, lo que hace que el foco salte entre secciones no relacionadas. Si necesitas un orden visual distinto al del código, reordena el DOM o usa CSS de layout, no tabindex positivo.

WCAG 2.4.3 Focus Order (Nivel A)
Preferir
1Nombre
2Apellido
3Email
4Telefono
orden del DOM = orden de lectura
Evitar
1Nombre
3Email
2Apellido
4Telefono
tabindex positivo: el foco salta en zigzag
251

El foco debe ser visible y no quedar tapado por headers sticky

Todo elemento que recibe foco de teclado debe mostrar un indicador visual claro (WCAG 2.4.7 Focus Visible, Nivel AA). Además, cuando el elemento enfocado queda bajo un header o footer sticky, WCAG 2.4.11 Focus Not Obscured (Nivel AA, WCAG 2.2) exige que no quede completamente oculto por contenido del autor; los sticky headers son el caso típico de fallo (Failure F110). La técnica documentada es html { scroll-padding-top: 80px }, que hace que el navegador deje margen sobre el elemento enfocado al hacer scroll. Nunca elimines el indicador de foco con outline:none sin reemplazo.

WCAG 2.4.7 Focus Visible (AA) · WCAG 2.4.11 Focus Not Obscured (AA, WCAG 2.2) · Failure F110
Preferir
Encabezado fijo
scroll-padding-top: 80px
Evitar
Encabezado fijo
foco oculto bajo el header
252

Usa inert en el fondo del modal y skip links en flujos largos

El atributo HTML inert aplicado al contenido detras de un modal lo vuelve completamente no interactivo de forma nativa: bloquea clicks, foco y eventos de foco, deshabilita la selección de texto, lo saca del find-in-page y lo oculta del arbol de accesibilidad. Es Baseline Widely Available desde abril 2023, lo que lo hace más robusto que las librerias de focus-trap en JS. Un modal con solo aria-modal="true" sin inert deja el fondo accesible para algunos lectores en modo browse. En wizards y flujos largos, complementa con skip links y landmarks ARIA para no recorrer todos los controles (WCAG 2.4.1 Bypass Blocks).

MDN inert (Baseline abr-2023) · WAI-ARIA APG Dialog · WCAG 2.4.1 Bypass Blocks (Nivel A)
Preferir
fondo inert
Confirmar
Evitar
solo aria-modal
Confirmar