Normative · ARIA

Ruolo Struttura del documento

tabpanel

Contrassegna il pannello dei contenuti associato a una scheda. Ogni tabpanel è etichettato dalla propria scheda tramite aria-labelledby; la scheda fa riferimento al pannello tramite aria-controls. Si visualizza un pannello alla volta; gli altri vengono nascosti con l'attributo hidden.

Quando utilizzarlo

Sul contenitore che racchiude il contenuto di una scheda. Si abbina ogni tabpanel alla propria scheda tramite aria-labelledby (che punta all’id della scheda). La scheda a sua volta punta al pannello con aria-controls. I pannelli inattivi vanno nascosti con l’attributo hidden — non solo con display: none via CSS — in modo che l’albero di accessibilità rifletta lo stato visivo.

Se il pannello contiene contenuto interattivo (un modulo, un elenco di link), è possibile rendere il pannello focalizzabile con tabindex="0". In questo modo, dopo aver attivato una scheda, il successivo tasto Tab atterrerà all’interno del pannello.

Se il pannello contiene una singola area focalizzabile — ad esempio un’intestazione principale seguita da contenuto — tabindex="0" sul pannello è sufficiente. Se il pannello è pieno di controlli interattivi, l’utente si sposterà su di essi direttamente con Tab e il tabindex è facoltativo.

Errori comuni

  • Tabpanel nascosto tramite CSS ma non tramite l’attributo hidden. Gli screen reader potrebbero comunque esporne il contenuto.
  • Tabpanel senza aria-labelledby — annunciato semplicemente come «pannello scheda» senza nome.
  • Il tab punta a un id del tabpanel tramite aria-controls ma il pannello non punta di rimando tramite aria-labelledby. L’abbinamento deve essere reciproco.
  • Tutti i tabpanel presenti nel DOM con display: none attivato dinamicamente, ma senza l’attributo hidden. I revisori segnalano questa incoerenza.
  • Applicazione di role="tabpanel" a un pannello NON abbinato a un role="tab" — tabpanel orfano.

Esempio

<div role="tablist" aria-label="Settings">
  <button role="tab" id="t-account" aria-selected="true"  aria-controls="p-account" tabindex="0">Account</button>
  <button role="tab" id="t-billing" aria-selected="false" aria-controls="p-billing" tabindex="-1">Billing</button>
</div>

<section role="tabpanel" id="p-account" aria-labelledby="t-account" tabindex="0">
  <h2>Account</h2>
  <p>…</p>
</section>
<section role="tabpanel" id="p-billing" aria-labelledby="t-billing" tabindex="0" hidden>
  <h2>Billing</h2>
  <p>…</p>
</section>