# 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.

> Pagina: https://ui.eneawork.it/blog/tabindex-uso-corretto
> Markdown: https://ui.eneawork.it/blog/tabindex-uso-corretto.md

*2026-11-01*

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.

Il rapporto WebAIM Million 2026, febbraio 2026, WAVE stand-alone API su 1.000.000 di homepage Tranco, pubblicato il 30 marzo 2026, conta 30,4 istanze di tabindex="0" o tabindex="-1" per pagina, il 17% in più del 2025 e quasi tre volte il valore del 2020; nella stessa rilevazione ci sono 23,3 aria-hidden="true" per pagina. Sul nostro corpus la misura è opposta: nelle 521 schede di data/blog il conteggio del 2 novembre 2026 trova 0 valori di tabindex positivi e 2 schede che nominano l'attributo. Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats il 1 novembre 2026.

## 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.

## FAQ

### 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.
