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.