Navegación por teclado
Si un control no se puede alcanzar y accionar solo con el teclado, no existe para una parte importante de tus usuarios — y ningún escáner automático te lo va a decir.
Qué falla
El acceso por teclado se rompe de cuatro maneras, y casi todos los hallazgos son una de ellas.
El control no es alcanzable. Un div con un manejador de clic no es focalizable. Parece un botón, se comporta como un botón para quien usa ratón, y es invisible para la secuencia de tabulación. Es la causa más frecuente, y llega con las librerías de componentes personalizados.
El control es alcanzable pero no accionable. El elemento recibe el foco, pero solo responde a click. Pulsar Intro o Espacio no hace nada. Quien usa ratón no lo nota nunca.
El foco entra y no puede salir. Un modal, un selector de fecha, un vídeo incrustado o un widget de terceros recibe el foco y no lo suelta. Es una trampa de teclado, y no termina la tarea: termina la sesión, porque la única salida es cerrar la pestaña.
El foco es invisible. Se quitó el contorno en CSS, normalmente con un outline: none en un reset, y no se puso nada en su lugar. La página es perfectamente operable y la persona no tiene ni idea de dónde está.
Nuevo en WCAG 2.2, hay un quinto caso ya muy común: foco que sí es visible pero queda tapado por una cabecera fija o un aviso de cookies. El indicador se dibuja bien, y debajo de otra cosa.
Cómo probarlo
Diez minutos, sin herramientas.
- Deja el ratón donde no lo alcances.
- Carga la página y pulsa Tabulador una vez. Debería aparecer un enlace para saltar al contenido.
- Recorre toda la página con el tabulador. Vigila el indicador de foco sin perderlo de vista.
- En cada elemento interactivo, pregúntate: ¿veo dónde estoy? ¿Intro o Espacio hacen lo que deberían?
- Abre cada modal, menú y desplegable. Tabula dentro. Pulsa Escape. Vuelve a salir con el tabulador.
- Completa la tarea principal: compra, envía el formulario, reserva la cita.
Apunta cada punto donde perdiste el indicador, no pudiste llegar, no pudiste salir o no supiste qué estaba enfocado. Esa lista es una auditoría de teclado.
Cómo corregirlo
Usa el elemento nativo. Esto resuelve por sí solo la mayoría de hallazgos. Un <button> es focalizable, se activa con Intro y Espacio, expone el rol de botón y funciona con control por voz. Un <div role="button" tabindex="0"> con un manejador de teclado es reimplementar todo eso, y la reimplementación es donde están los fallos.
<!-- No alcanzable, no accionable, sin rol -->
<div class="btn" onclick="enviar()">Enviar</div>
<!-- Alcanzable, accionable, anunciado correctamente -->
<button type="button" onclick="enviar()">Enviar</button>
Nunca quites el indicador de foco sin sustituirlo. Si el anillo por defecto no encaja con el diseño, dibuja uno mejor — pero tiene que cumplir 3:1 contra su fondo y ser visible sobre todos los fondos por los que pase el elemento.
/* El problema */
:focus { outline: none; }
/* Un sustituto que de verdad se ve */
:focus-visible {
outline: 2px solid var(--color-foco);
outline-offset: 2px;
}
Gestiona el foco cuando aparece contenido. Al abrir un diálogo, lleva el foco dentro. Mantenlo dentro mientras esté abierto. Al cerrarlo, devuélvelo al control que lo abrió — si no, el foco vuelve al principio del documento y la persona empieza la página de nuevo.
Mantén el mismo orden en el DOM y en pantalla. order en CSS, flex-direction: row-reverse y el posicionamiento absoluto pueden reordenar lo que se ve sin reordenar lo que se tabula. Si los dos no coinciden, la secuencia de foco salta por la pantalla.
Comprueba qué tapa tu cabecera fija. Añade scroll-margin-top a los elementos focalizables, o reduce la zona fija, para que el foco no quede nunca dibujado por debajo.
Por qué importa comercialmente
Las barreras de teclado son las que detienen una transacción, no las que la empeoran. Un fallo de contraste hace tu checkout más difícil de leer; una trampa de foco en el modal de pago lo hace imposible de completar. En una auditoría, los hallazgos de teclado están sobrerrepresentados en la franja crítica precisamente por eso.