Qué es un tabindex positivo (y por qué rompe la navegación por teclado)
Todo desarrollador termina topándose con un orden de tabulación roto. El foco salta del encabezado directo al pie de página y se saltea la barra lateral. El botón de cierre de un modal es lo último que alcanza el teclado. Entonces alguien coloca tabindex="3" en un par de elementos, tabula una vez, ve que “funciona” y lo publica.
Seis meses después nadie puede explicar por qué la navegación por teclado de esa página es un caos para todos los demás.
El tabindex positivo es el arreglo clásico que parece una solución y en realidad es un error a cámara lenta. Veamos qué hace de verdad y qué conviene usar en su lugar.
Cómo funciona tabindex
El atributo tabindex controla si un elemento puede recibir foco y dónde se ubica en la secuencia de tabulación. Tiene tres estados significativos:
tabindex="-1": Focusable mediante programación (con.focus()de JavaScript), pero eliminado de la secuencia natural de tabulación.tabindex="0": Se une a la secuencia natural de tabulación en su posición en el DOM. Útil para hacer focusables por teclado elementos no interactivos (como un widget<div>personalizado).tabindex="N"donde N > 0: Un tabindex positivo. Aquí es donde las cosas salen mal.
Los elementos con un tabindex positivo se enfocan primero, por delante de todo lo que está en el flujo normal, en orden numérico ascendente. Así, tabindex="1" va antes que tabindex="2", que va antes que tabindex="3". Solo cuando ese grupo positivo se agota, el navegador vuelve al orden del código fuente para los elementos con tabindex="0" y los enfocables de forma nativa. (Los elementos que comparten el mismo valor positivo se recorren entre sí en orden del DOM.)
Por qué el tabindex positivo rompe la navegación
Imagina una página con una barra de navegación en la parte superior, un área de contenido principal y un pie de página. El orden en el DOM es sensato — nav, luego contenido, luego pie de página. Pero alguien agregó tabindex="2" a un botón “Suscribirse” en el pie de página y tabindex="1" a un enlace en la barra lateral.
Esto es lo que sucede cuando un usuario de teclado presiona Tab en esa página:
- Enlace de la barra lateral (
tabindex="1") - Botón Suscribirse en el pie de página (
tabindex="2") - Todos los demás elementos interactivos en el nav
- Todos los demás elementos interactivos en el contenido
- Todo lo demás en el pie de página
Al usuario lo arrastran al final de la página y luego de vuelta arriba, antes de que el diseño que ve en pantalla tenga algo que decir. Y acá está la parte que sorprende: esos dos atributos no reordenaron solo dos elementos. Reordenaron la página entera. En cuanto existe un tabindex positivo, todos los demás elementos enfocables quedan detrás de él, así que el orden natural se rompe para todo el documento, no para el único botón que tocaste.
Eso golpea de lleno el Criterio de Conformidad 2.4.3 (Orden del foco) de WCAG 2.1 en el Nivel A, que exige que la secuencia de foco preserve el significado y la operabilidad. Cuando el orden de navegación y el de lectura se separan, también puedes incumplir el SC 1.3.2 (Secuencia con significado).
El problema real que el tabindex positivo “resuelve”
Nueve de cada diez veces, recurrir a tabindex="2" significa que el orden del DOM y el orden visual se separaron. Una barra lateral aparece a la izquierda en pantalla pero viene después del contenido principal en el código fuente. Un encabezado fijo está escrito al final de la plantilla. Un diseño con Grid o Flexbox reacomoda las cajas en pantalla sin mover un solo nodo en el DOM.
Esa discrepancia es el error real, y tabindex no lo corrige. Solo lo oculta. La solución es alinear el orden del DOM con el orden por el que quieres que la gente avance.
<!-- Incorrecto: el CSS pinta el aside a la izquierda, pero viene después de main en el DOM -->
<main>...</main>
<aside>...</aside>
<!-- Correcto: el orden del DOM coincide con el orden de lectura/navegación previsto -->
<aside>...</aside>
<main>...</main>
Aquí tienta recurrir a la propiedad CSS order (o a flex-direction: row-reverse y similares), pero eso te deja en la misma trampa. Tanto MDN como las técnicas de WCAG lo señalan: order repinta la secuencia visual sin tocar el orden del foco, así que los usuarios de teclado y de lector de pantalla siguen recorriendo el orden del DOM mientras los usuarios videntes con mouse ven otro diseño. Úsalo para reacomodos puramente cosméticos, nunca para “arreglar” la navegación. Alinear el DOM sigue siendo la única solución real.
Cuándo tabindex=“0” es apropiado
tabindex="0" es la forma segura y compatible con los estándares de agregar foco por teclado a un widget interactivo personalizado que no es un elemento HTML nativo:
<!-- Un toggle personalizado que necesita ser focusable por teclado -->
<div
role="switch"
tabindex="0"
aria-checked="false"
aria-label="Activar notificaciones"
>
<!-- contenido visual -->
</div>
Pero antes, pregúntate si un elemento nativo haría el trabajo. Un <button>, <a href>, <input>, <select> o <textarea> recibe foco de fábrica, trae el comportamiento de teclado que de otro modo tendrías que reimplementar (activación con Espacio y Enter, manejo de flechas) y no necesita JavaScript para ser operable. El role="switch" personalizado de arriba, además, te obliga a escribir un manejador de teclado para alternarlo; un <input type="checkbox"> nativo no. El mejor patrón ARIA suele ser no usar ARIA en absoluto.
Cuándo tabindex=“-1” es apropiado
tabindex="-1" es útil para gestionar el foco mediante programación — por ejemplo, mover el foco a un diálogo modal cuando se abre, o a un mensaje de error después de que falla la validación de un formulario:
<div id="error-summary" tabindex="-1" role="alert">
Por favor corrige los siguientes errores antes de enviar.
</div>
document.getElementById('error-summary').focus();
Esto hace que el error sea visible para los lectores de pantalla sin poner el resumen de errores en la secuencia natural de tabulación, donde confundiría a los usuarios que navegan normalmente por el formulario.
Cómo auditar el orden de tabulación
Los errores de orden de tabulación son traicioneros porque no aparecen donde sueles mirar. Una captura de pantalla no los revela. Una revisión de código tampoco, a menos que quien revisa alcance a ver un tabindex perdido en el diff. La única forma honesta de saberlo es recorrer la página con el teclado.
El método manual: cargar la página, hacer clic en un lugar vacío para que nada tenga foco, presionar Tab una y otra vez y anotar el orden. Compararlo con el flujo visual.
Funciona. También es lento, y hay que rehacerlo cada vez que el diseño cambia.
La herramienta Tab Order de PxGuard visualiza la secuencia de foco directamente en la página — con indicadores numerados en cada elemento focusable en el orden en que recibirán el foco. Se puede detectar un tabindex positivo que saca cosas de secuencia de un vistazo, sin presionar Tab cuarenta veces. Es especialmente útil al auditar páginas con diseños complejos, modales o contenido añadido dinámicamente.
Consulta la documentación para saber cómo leer la superposición de Tab Order y filtrar por elementos focusables.
Para una revisión de accesibilidad más amplia, esto se combina naturalmente con las verificaciones de botones de icono accesibles y el flujo de trabajo de verificación WCAG en 5 minutos.
La regla general
Cuando te descubras escribiendo tabindex="1" (o cualquier número positivo), detente y hazte la pregunta de fondo: ¿por qué el orden del DOM no coincide con el orden por el que la gente debería avanzar? Corrige el orden del código fuente. Si eso de verdad está fuera de tu alcance, por ejemplo un widget de terceros con un DOM que no puedes tocar, anota la excepción y vive con la limitación en lugar de embadurnar la página de tabindices positivos para que el próximo desarrollador los desenrede.
En la práctica, tabindex tiene dos valores que vale la pena usar: 0 y -1. Cualquier valor positivo casi siempre es señal de que hay otra cosa que arreglar.
Pruébalo en tus propias páginas
PxGuard es una extensión de Chrome gratuita. Inspecciona espaciado, tipografía y accesibilidad en segundos.
Instalar gratis