Utilizzare tabindex

Modifica dell'ordine DOM con tabindex

Dave Gash
Dave Gash
Meggin Kearney
Meggin Kearney

L'ordine predefinito delle schede fornito dalla posizione DOM degli elementi nativi è pratico, ma a volte potresti voler modificare l'ordine delle schede e lo spostamento fisico degli elementi nell'HTML non è sempre una soluzione ottimale o fattibile. In questi casi puoi usare l'attributo HTML tabindex per impostare esplicitamente la posizione della scheda di un elemento.

Supporto dei browser

  • 1
  • 12
  • 1,5
  • ≤4

Fonte

tabindex può essere applicato a qualsiasi elemento, anche se non è necessariamente utile per ogni elemento, e prende un intervallo di valori interi. Utilizzando tabindex, puoi specificare un ordine esplicito degli elementi della pagina attivabili, inserire un elemento che altrimenti non è attivabile nell'ordine delle schede e rimuovere elementi dall'ordine delle schede. Ad esempio:

tabindex="0": inserisce un elemento nell'ordine di tabulazione naturale. È possibile impostare lo stato attivo dell'elemento premendo il tasto Tab e lo stato attivo chiamando il metodo focus()

<custom-button tabindex="0">Press Tab to Focus Me!</custom-button>

Premi Tab per concentrarmi

tabindex="-1": rimuove un elemento dall'ordine delle schede naturali, ma può comunque essere attivato richiamando il relativo metodo focus()

// TODO: DevSite - Code sample removed as it used inline event handlers

// TODO: DevSite - Esempio di codice rimosso poiché utilizzava gestori di eventi incorporati

tabindex="5": qualsiasi indice di tabulazione maggiore di 0 porta l'elemento in primo piano nell'ordine delle schede naturale. Se ci sono più elementi con un tabindex maggiore di 0, l'ordine delle tabulazioni inizia dal valore più basso maggiore di zero e continua a crescere. L'utilizzo di un valore tabindex maggiore di 0 è considerato un anti-pattern.

<button>I should be first</button>
<button>And I should be second</button>
<button tabindex="5">But I jumped to the front!</button>

Questo vale in particolare per gli elementi non di input come intestazioni, immagini o titoli di articoli. Aggiungere tabindex a questi tipi di elementi è controproducente. Se possibile, ti consigliamo di organizzare il codice sorgente in modo che la sequenza DOM fornisca un ordine logico delle schede. Se utilizzi tabindex, limitalo a controlli interattivi personalizzati come pulsanti, schede, menu a discesa e campi di testo, ovvero gli elementi a cui l'utente potrebbe aspettarsi di fornire input.

Non preoccuparti che gli utenti di screen reader perdano contenuti importanti perché non hanno un tabindex. Anche se i contenuti sono molto importanti, come un'immagine, se non c'è qualcosa con cui l'utente può interagire, non c'è motivo di renderlo attivabile. Gli utenti di screen reader possono comunque comprendere il contenuto dell'immagine purché tu fornisca un adeguato supporto per gli attributi alt, di cui parleremo a breve.

Gestione dello stato attivo a livello di pagina

Ecco uno scenario in cui tabindex non è solo utile, ma necessario. Potresti creare una singola pagina efficace con diverse sezioni di contenuti, non tutte visibili contemporaneamente. Se fai clic su un link di navigazione in una pagina simile, potresti modificare i contenuti visibili senza dover aggiornare la pagina.

In questi casi, probabilmente dovresti identificare l'area di contenuti selezionata, assegnare un valore tabindex pari a -1 in modo che non venga visualizzata nell'ordine della scheda naturale e chiamare il relativo metodo focus. Questa tecnica, chiamata gestione dello stato attivo, mantiene sincronizzato il contesto percepito dall'utente con i contenuti visivi del sito.

Gestione dell'attenzione per i componenti

Gestire lo stato attivo quando modifichi un elemento nella pagina è importante, ma a volte è necessario gestirlo a livello di controllo, ad esempio se stai creando un componente personalizzato.

Considera l'elemento select nativo. Potrebbe essere concentrata di base, ma potrai usare i tasti freccia per mostrare ulteriori funzionalità (le opzioni selezionabili). Se stessi creando un elemento select personalizzato, dovresti esporre questi stessi comportamenti in modo che gli utenti che si affidano principalmente alla tastiera possano comunque interagire con il tuo controllo.

<!-- Focus the element using Tab and use the up/down arrow keys to navigate -->
<select>
    <option>Aisle seat</option>
    <option>Window seat</option>
    <option>No preference</option>
</select>

Sapere quali comportamenti della tastiera implementare può essere difficile, ma c'è un documento utile a cui puoi fare riferimento. La guida alle pratiche di authoring per le applicazioni ARIA (Accessible Rich Internet Applications) elenca i tipi di componenti e i tipi di azioni da tastiera supportati. Parleremo più dettagliatamente di ARIA più avanti, ma per ora usiamo la guida per aggiungere il supporto della tastiera a un nuovo componente.

Magari stai lavorando ad alcuni nuovi elementi personalizzati che ricordano un insieme di pulsanti di opzione, ma con un aspetto e un comportamento unici.

<radio-group>
    <radio-button>Water</radio-button>
    <radio-button>Coffee</radio-button>
    <radio-button>Tea</radio-button>
    <radio-button>Cola</radio-button>
    <radio-button>Ginger Ale</radio-button>
</radio-group>

Per determinare di che tipo di supporto per la tastiera hanno bisogno, consulta la guida alle pratiche di creazione ARIA. La sezione 2 contiene un elenco di pattern di progettazione, sotto il quale c'è una tabella delle caratteristiche per i gruppi di pulsanti di opzione, il componente esistente che corrisponde meglio al nuovo elemento.

Come puoi vedere nella tabella, uno dei comportamenti comuni della tastiera che devono essere supportati è i tasti freccia su/giù/sinistra/destra. Per aggiungere questo comportamento al nuovo componente, utilizzeremo una tecnica chiamata tabindex mobile.

Estratto delle specifiche W3C per i pulsanti di opzione.

Il tabindex roving funziona impostando tabindex su -1 per tutti i publisher secondari, tranne quello attualmente attivo.

<radio-group>
    <radio-button tabindex="0">Water</radio-button>
    <radio-button tabindex="-1">Coffee</radio-button>
    <radio-button tabindex="-1">Tea</radio-button>
    <radio-button tabindex="-1">Cola</radio-button>
    <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

Il componente utilizza quindi un listener di eventi della tastiera per determinare il tasto premuto dall'utente; in questo caso, imposta su -1 il valore tabindex dell'elemento figlio attivo in precedenza, imposta il valore tabindex dell'elemento figlio su cui concentrarti su 0 e richiama il metodo di stato attivo su questo elemento.

<radio-group>
    // Assuming the user pressed the down arrow, we'll focus the next available child
    <radio-button tabindex="-1">Water</radio-button>
    <radio-button tabindex="0">Coffee</radio-button> // call .focus() on this element
    <radio-button tabindex="-1">Tea</radio-button>
    <radio-button tabindex="-1">Cola</radio-button>
    <radio-button tabindex="-1">Ginger Ale</radio-button>
</radio-group>

Quando l'utente raggiunge l'ultimo (o il primo), a seconda della direzione in cui sposta l'elemento attivo, eseguirai un loop e lo occuperai di nuovo del primo (o dell'ultimo) elemento secondario.

Puoi provare l'esempio completato in basso. Esamina l'elemento in DevTools per osservare come il tabindex si sposti da una radio all'altra.

Acqua Caffè Cola Ginger Ale

// TODO: DevSite - Esempio di codice rimosso poiché utilizzava gestori di eventi incorporati

Puoi visualizzare il codice sorgente completo di questo elemento su GitHub.

Modali e trappole per tastiera

A volte, quando gestisci la concentrazione, puoi entrare in una situazione da cui non riesci a uscire. Prendi in considerazione un widget di completamento automatico che tenta di gestire lo stato attivo e acquisisce il comportamento della scheda, ma impedisce all'utente di abbandonarlo fino al completamento. Questa operazione è chiamata trappola da tastiera e può essere molto frustrante per l'utente. La sezione 2.1.2 dell'elenco di controllo Web AIM risolve questo problema, indicando che l'elemento attivo della tastiera non deve mai essere bloccato o incastrato in un particolare elemento di pagina. L'utente deve essere in grado di spostarsi da e verso tutti gli elementi della pagina utilizzando soltanto la tastiera.

Stranamente, a volte questo comportamento è effettivamente auspicabile, ad esempio in una finestra modale. Normalmente, quando la finestra modale è visualizzata, non vuoi che l'utente acceda ai contenuti sottostanti. Potresti aggiungere un overlay per coprire visivamente la pagina, ma questo non impedisce allo stato attivo della tastiera di spostarsi per errore al di fuori della finestra modale.

Una finestra modale che chiede all&#39;utente di salvare il proprio lavoro.

In casi come questo, puoi implementare un blocco da tastiera temporaneo per assicurarti di bloccare lo stato attivo solo mentre la finestra modale è visualizzata e poi di ripristinare lo stato attivo sull'elemento precedentemente attivo quando la finestra modale è chiusa.

Esistono alcune proposte su come semplificare questa operazione per gli sviluppatori, tra cui l'elemento <dialog>, ma il browser non è ancora supportato su larga scala da parte degli sviluppatori.

Consulta questo articolo su MDN per ulteriori informazioni su <dialog> e questo esempio modale per ulteriori informazioni sulle finestre modali.

Considera una finestra di dialogo modale rappresentata da un div che contiene alcuni elementi e da un altro div che rappresenta un overlay di sfondo. Analizziamo i passaggi di base necessari per implementare un blocco della tastiera temporaneo.

  1. Utilizzando document.querySelector, seleziona i div modali e in overlay e memorizza i relativi riferimenti.
  2. Quando la finestra modale si apre, memorizza un riferimento all'elemento attivo quando è stata aperta la finestra modale, in modo da poter ripristinare lo stato attivo su quell'elemento.
  3. Utilizza un ascoltatore keydown per trascinare i tasti quando vengono premuti mentre la finestra modale è aperta. Puoi anche ascoltare un clic sull'overlay di sfondo e chiudere la finestra modale se l'utente vi fa clic.
  4. Quindi, ottieni la raccolta di elementi attivabili all'interno della finestra modale. Il primo e l'ultimo elemento attivabile fungeranno da "sentinel" per farti sapere quando eseguire il loop di messa a fuoco in avanti o indietro per rimanere all'interno della finestra modale.
  5. Visualizza la finestra modale e imposta lo stato attivo sul primo elemento attivabile.
  6. Quando l'utente preme Tab o Shift+Tab, sposta lo stato attivo in avanti o indietro, creando in loop l'ultimo o il primo elemento, a seconda dei casi.
  7. Se l'utente preme Esc, chiudi la finestra modale. Ciò è molto utile perché consente all'utente di chiudere la finestra modale senza cercare un pulsante di chiusura specifico e avvantaggia anche gli utenti che utilizzano un mouse.
  8. Quando la finestra modale è chiusa, nascondila e l'overlay di sfondo e ripristina lo stato attivo sull'elemento precedentemente salvato.

Questa procedura ti fornisce una finestra modale utilizzabile e non frustrante che chiunque può usare in modo efficace.

Per ulteriori dettagli, puoi esaminare questo codice campione e visualizzare un esempio in tempo reale da una pagina completa.