Trampa de foco
El patrón que mantiene el foco de teclado dentro de un diálogo modal mientras está abierto: impide que Tab escape al documento subyacente y devuelve el foco al elemento que abrió el diálogo al cerrarlo.
Una trampa de foco es una restricción deliberada de la navegación por teclado: mientras un diálogo modal está abierto, Tab recorre únicamente los elementos enfocables dentro de ese diálogo. Shift+Tab recorre en sentido contrario. El usuario no puede salir del modal con Tab hacia el contenido de la página —visualmente bloqueado— hasta que lo cierra de forma explícita.
La trampa de foco es obligatoria en los diálogos modales accesibles. Sin ella, los usuarios de teclado y de lectores de pantalla aterrizan en contenido de página invisible que no pueden ver ni del que pueden escapar.
Por qué es necesario
Un diálogo modal se presenta visualmente como una capa por encima de la página. La intención —sin ambigüedad— es que el usuario interactúe con el modal hasta terminar y luego regrese a la página. Para los usuarios de ratón esto es intuitivo: hacer clic fuera del modal no hace nada (o lo cierra); hacer clic dentro alcanza los controles del modal.
Sin una trampa de foco, los usuarios de teclado obtienen una experiencia inconsistente:
- El modal se abre. El foco se mueve (o debería moverse) al primer elemento enfocable dentro del modal.
- El usuario presiona Tab. El foco pasa al siguiente elemento enfocable dentro del modal.
- El usuario continúa presionando Tab. El foco llega al último elemento enfocable dentro del modal.
- Un Tab más. Sin trampa, el foco salta al siguiente elemento enfocable en el documento —que se encuentra detrás del modal, invisible para el usuario.
La única señal de que esto ha ocurrido es que el indicador de foco del modal desaparece. El usuario no sabe en absoluto dónde está su foco.
El patrón completo de modal accesible
Un modal accesible completo incluye:
- El foco entra en el modal al abrirse —normalmente al primer
elemento enfocable o al encabezado del modal (si el encabezado tiene
tabindex="-1"para el foco programático). - El foco queda atrapado dentro del modal: Tab desde el último elemento vuelve al primero; Shift+Tab desde el primero vuelve al último.
- Escape cierra el modal y devuelve el foco al elemento que lo abrió —no al cuerpo del documento.
- Hacer clic fuera del modal lo cierra — comportamiento opcional; no todos los modales hacen esto, pero si el modal lo implementa, el foco debe seguir atrapado mientras esté abierto.
role="dialog"yaria-modal="true"en el elemento modal, conaria-labelledbyapuntando al encabezado del modal.
Implementaciones
La biblioteca más citada es focus-trap (npm: focus-trap,
focus-trap-react, focus-trap-vue) — ligera, sin dependencias y
capaz de gestionar todos los casos extremos (omitir elementos
invisibles, integrarse con inert, restaurar el foco al cerrar).
El elemento nativo moderno es <dialog> con dialog.showModal(),
que atrapa el foco automáticamente y gestiona el cierre con Escape.
La compatibilidad de navegadores es ahora suficientemente amplia para
usarlo como línea base.
Antipatrón: la «trampa que no suelta»
Una trampa de foco debe liberarse cuando el modal se cierra. El error de implementación más habitual es olvidar restaurar el foco al elemento original que lo activó: el foco acaba en el cuerpo del documento, que los lectores de pantalla anuncian como nada. El usuario cae en silencio y tiene que volver a recorrer la página desde el principio con Tab.