Accessibilità
tabindex: l'unico uso corretto
tabindex 0 serve su un widget custom che ha anche ruolo e gestione da tastiera; -1 serve al focus via script. I valori positivi riordinano la tabulazione e la rompono.
In sintesi
- tabindex="-1" toglie un elemento dall'ordine di tabulazione ma lo lascia focusabile via script: è l'uso legittimo più frequente.
- Un valore positivo mette l'elemento davanti a tutti quelli con tabindex 0, in ordine crescente, e rompe il criterio 2.4.3.
- tabindex non crea semantica né tastiera: su un div serve anche un ruolo e la gestione di Enter, Space e frecce.
L'unico uso corretto di tabindex è 0 su un widget custom a cui dai anche un ruolo e la gestione da tastiera, e -1 per portare il focus via codice. I valori positivi non servono a nessun componente: riordinano la tabulazione e la rompono.
0 e -1 non sono la stessa cosa
tabindex="0" inserisce l'elemento nell'ordine naturale del documento, nel punto in cui si trova nel DOM. tabindex="-1" lo rende focusabile solo per programma: resta fuori dalla sequenza di Tab, ma element.focus() lo raggiunge. Il primo serve a rendere operabile un widget che hai costruito; il secondo a spostare il focus dove il codice decide.
Perché i valori positivi sono sempre un errore
Con un valore positivo la sequenza cambia: prima tutti gli elementi con tabindex="1", poi quelli con 2, e solo alla fine quelli con 0 e senza attributo, nell'ordine del DOM. Il criterio 2.4.3 chiede che l'ordine di focus preservi significato e operabilità; un ordine che salta dalla testata al piè di pagina per poi tornare indietro lo viola. Il costo di manutenzione è la parte peggiore: ogni nuovo elemento può richiedere una rinumerazione completa.
Il caso legittimo: una destinazione per il focus
Uno skip link funziona solo se il bersaglio può ricevere il focus. Su un <main> senza tabindex="-1" il browser sposta la vista ma il focus resta sul link, e il Tab successivo riparte dall'inizio. Lo stesso vale per il contenitore di un modale e per il riepilogo degli errori dopo l'invio di un form.
Skip to content
Orders
document.querySelector('.skip-link').addEventListener('click', (event) => {
event.preventDefault();
document.querySelector('#main').focus();
});
Roving tabindex nei widget compositi
Una tablist, un menu o un radiogroup occupano un solo stop di tabulazione: l'elemento attivo ha tabindex="0", gli altri -1. Le frecce spostano il focus e aggiornano lo stato, quindi aria-selected o aria-checked cambiano insieme al valore di tabindex. Senza questo pattern il criterio 2.1.1 resta scoperto: il widget si raggiunge ma non si usa.
Come verificarlo
Il test manuale è breve: premi Tab dall'inizio della pagina e conta i passaggi; se il focus salta in avanti e poi torna indietro, c'è un valore positivo nel DOM. Axe ha una regola dedicata e la cli si installa con npm.
npx --yes @axe-core/cli https://example.com --tags wcag2a,wcag2aa
Il comando restituisce le violazioni con selettore e criterio. La regola su tabindex positivo è fra quelle che un tool trova davvero: il resto, cioè se il widget risponde alle frecce, lo verifichi solo da tastiera.
Il catalogo EneUI
Un record verificato è navigation-menu di Shadcn, licenza MIT dichiarata a monte: la navigazione da tastiera e la gestione del focus arrivano dalla primitiva, non da un tabindex scritto a mano. Gli altri casi sono in blocchi menu e accessibilità. Controllo eseguito il 1 novembre 2026 sul catalogo da 111.985 componenti.
La limitazione
tabindex cambia solo la raggiungibilità con Tab. Non ripara un ordine del DOM sbagliato, non crea un ruolo e non convince un lettore di schermo in modalità lettura, dove il movimento avviene per elementi e non per focus. Se l'ordine visivo è corretto e quello del DOM no, il problema è di layout e si risolve con CSS, non con attributi.
Dove continuare
Il focus visibile è trattato in focus ring invisibile; la checklist completa è in componenti React accessibili. L'errore speculare, un nome che contraddice il testo, è in aria-label sui bottoni.
Domande frequenti
Posso usare tabindex su un div?
Solo con un ruolo e la gestione da tastiera. Un div con tabindex="0" e nient'altro è un controllo che si raggiunge ma non si attiva, e viola 4.1.2.
Perché tabindex="1" è un problema?
Perché i valori positivi vengono prima di tutti gli zeri, in ordine crescente. Basta aggiungere un elemento per dover rinumerare tutto, e l'ordine visivo non corrisponde più.
Quando serve tabindex="-1"?
Quando il codice deve spostare il focus su un contenitore: destinazione di uno skip link, primo elemento di un modale, riepilogo degli errori dopo l'invio.
tabindex="-1" toglie il focus ring?
No, il ring resta se lo stile non lo sopprime. Non usare outline: none per nasconderlo: chi naviga da tastiera perde l'unico segnale di posizione.
Che cos'è il roving tabindex?
Un pattern per tab, menu e radiogroup: l'elemento attivo ha tabindex="0", gli altri tabindex="-1", e le frecce spostano focus e stato. Un solo stop di tabulazione per l'intero widget.