Questa traduzione è incompleta. Collabora alla traduzione di questo articolo dall’originale in lingua inglese.

Proseguendo i temi trattati nell'articolo precedente, può risultare complicato creare elementi di interfaccia utente accessibili quando si basano su HTML non semantico e presentano contenuto aggiornato dinamicamente tramite JavaScript. La tecnologia WAI-ARIA può essere d'aiuto, aggiungendo ulteriori valori semantici che i browser e le tecnologie assistive possono riconoscere e utilizzare per permettere agli utenti di decifrare più chiaramente il contesto e ciò che sta accadendo durante la navigazione del sito. Qui vi mostreremo come usare questa tecnologia a un livello basico per migliorare l'accessibilità.

Prerequisiti: Conoscimenti basici sull'uso del computer, livello basico di HTML, CSS e JavaScript, aver letto i precedenti articoli del corso.
Obiettivo: Acquisire familiarità con la tecnologia WAI-ARIA e imparare a usarla dove necessario per fornire valore semantico addizionale che migliori l'accessibilità.

Cosa è WAI-ARIA?

Cominciamo col dare un'occhiata a cosa è WAI-ARIA, e in che modo ci può essere utile.

Un nuovo set di problemi

Man mano che le applicazioni web cominciarono ad essere sempre più complesse e dinamiche, un nuovo set di problemi di accessibilità iniziò a manifestarsi.

Per esempio, l'HTML5 ha introdotto alcuni elementi semantici per definire componenti di uso comune nelle pagine  (<nav>, <footer>, ecc.). Prima dell'arrivo di questi elementi, gli sviluppatori si limitavano a usare <div> con ID o classi, per esempio <div class="nav">. Ma questi elementi erano problematici, perchè non fornivano un sistema standard per individuare programmaticamente i componenti di una pagina. 

La soluzione inizialmente consisteva in aggiungere uno o più link nascosti nella parte alta della pagina. Tali link reindirizzavano alle varie sezioni della pagina, come per esempio la barra di navigazione:
 

<a href="#hidden" class="hidden">Vai alla barra di navigazione</a>

Ma questo sistema non è molto preciso, e può essere usato solo quando il lettore di schermo comincia a leggere dalla parte alta della pagina.

Per fare un altro esempio, in un certo momento le applicazioni cominciarono a includere controlli complessi come selezionatori di data o slider per selezionare valori, ecc. HTML5 mette a disposizione alcuni tipi speciali di input specifici per tali controlli:

<input type="date">
<input type="range">

Ma questi elementi non sono supportati da tutti i browser, ed inoltre sono molto difficili da personalizzare, rendendoli complicati da integrare nel disegno di un sito. Di conseguenza, gli sviluppatori spesso fanno uso di librerie JavaScript e creano tali controlli come una serie di <div> annidati o elementi di una tabella a cui assegnano classi, e in seguito li personalizzano con CSS e li controllano con funzioni di JavaScript.

Il problema con questo mnetodo è che i lettori di schermo non riescono ad interpretare di cosa si tratta, e riportano solo la presenza di una serie di elementi dei quali non possono descrivere la funzione.

E arrivò WAI-ARIA

WAI-ARIA è una specifica, cioè una raccolta di indicazioni, prodotta dal W3C, che definisce una serie di attributi HTML addizionali che possono essere applicati agli elementi per fornire maggior valore semantico e migliorare l'accessibilità dovunque sia necessario. Ci sono tre caratteristiche principali definite nella raccolta:  

  • Ruoli — I ruoli (role) definiscono cosa un elemento è e qual è la sua funzione. Molti sono cosiddetti ruoli di riferimento, che in sostanza replicano il valore semantico degli elementi HTML5. Per esempio role="navigation" (<nav>) o role="complementary" (<aside>). Ma ce ne sono anche altri che definiscono differenti strutture della pagina, come role="banner", role="search", role="tabgroup", role="tab", ecc., che si trovano comunemente nelle IU (Interfacce Utente).
  • Proprietà — Si tratta delle proprietà degli elementi, che si possono usare per dare agli stessi un significato extra. per esempio, aria-required="true" specifica che il campo di un formulario deve essere obbligatoriamente riempito per essere valido, mentre aria-labelledby="label"  permette di assegnare una ID a un elemento e in seguito usare l'elemento come etichetta per qualsiasi altro elemento nella pagina, anche per multipli elementi, cosa che non è possibile con <label for="input">. Per esempio, potresti usare aria-labelledby per specificare che una descrizione contenuta in un <div> si usi come etichetta per multiple celle di una tabella, o come testo alternativo di una immagine, senza doverlo ripetere nell'attributo alt. Puoi vedere un esempio d'uso nella sezione Alternative testuali.
  • Stati — GLi stati sono proprietà speciali che definiscono le condizioni correnti degli elementi, come per esempio aria-disabled="true", che specifica a un lettore di schermo che un campo di input di un formulario è al momento disabilitato. Gli stati si distinguono dalle proprietà per il fatto che le proprietà non cambiano durante il ciclo vitale di un'applicazione, mentre gli stati possono essere cambiati, in genere tramite l'uso di JavaScript.

Un punto importante da tenere in considerazione riguardo gli attributi WAI-ARIA è che non influiscono in alcun modo sulla pagina, eccetto che sulle informazioni fornite dalla API di accessibilità del browser (dalla quale i lettori di schermo prendono le informazioni). WAI-ARIA non cambia la struttura della pagina, il DOM ecc. anche se i suoi attributi possono essere utili per selezionare gli elementi in CSS.

Nota: puoi trovare una utile lista di tutti i ruoli ARIA e i loro usi, con link a informazioni più approfondite, nella specifica WAI-ARIA: vedi Definizione di Ruoli (in inglese).

La specifica contiene anche una lista delle proprietà e degli stati, con link ad ulteriori informazioni. Vedi Definizioni di Stati e Proprietà (in inglese).

Dove è supportata WAI-ARIA?

A questa domanda non è facile rispondere. È difficile trovare  una risorsa che indichi in maniera completa quali funzionalità di WAI-ARIA sono supportate e dove, perchè:

  1. Ci sono molte funzionalità nella specifica WAI-ARIA.
  2. Ci sono moltissime combinazioni possibili di sistemi operativi, browser e lettori di schermo.

L'ultimo punto è fondamentale: per poter usare un lettore di schermo il tuo sistema operativo deve avere installato almeno un browser con la necessaria API di accessibilità che fornisca ai lettori di schermo le informazioni necessarie perchè funzionino. La maggior parte dei sistemi operativi ha di serie uno o due browser che funzionano con i lettori di schermo. Sul sito di Paciello Group si può trovare una guida aggiornata costantemente che fornisce dati sul supporto dei lettori di schermo nei vari sistemi operativi. Vedi l'articolo (in inglese) Guida: browser, sistemi operativi e supporto per i lettori di schermo.

Il seguente passo è assicurarsi che i browser usati supportino la tecnologia ARIA e la trasmettano tramite le loro API, ma anche che i lettori di schermo riconoscano le informazioni che ricevono e le presentino agli utenti in una forma ottimale.

  1. Il supporto dei browser in generale è molto buono. Al momento della stesura di questo articolo, il sito caniuse.com riporta un livello globale di supporto di WAI-ARIA nei vari browser di circa l'88%.
  2. Il supporto di ARIA nei lettori di schermo non è al momento a un livello comparabile, ma i lettori di schermo più popolari stanno facendo grandi sforzi per migliorare la compatibilità con WAI-ARIA.  Puoi farti un'idea del livello di supporto leggendo l'articolo (in inglese) Compatibilità dei lettori di schermo con WAI-ARIA .

In questo articolo non spiegheremo tutte le funzionalità di WAI-ARIA e i dettagli del supporto che hanno. Cercheremo invece di presentare le funzionalità più importanti e utili agli sviluppatori web; in generale se non facciamo riferimento al livello di supporto di una funzionalità, puoi considerare che il supporto è buono. In caso di eccezione lo indicheremo esplicitamente.
 

Nota: alcune librerie JavaScript supportano WAI-ARIA. Ciò significa che quando generano elementi IU, come per esempio formulari complessi, aggiungono automaticamente attributi ARIA per migliorarne l'accessibilità. Se stai valutando l'utilizzo di una libreria Javascript per sviluppare elementi IU più rapidamente, dovresti tenere in conto il livello di accessibilità degli elementi quando scegli quale libreria usare. Buoni esempi sono jQuery UI (vedi l'articolo in inglese jQuery UI: supporto all'accessibilità), ExtJS, e Dojo/Dijit.

Quando dovresti usare WAI-ARIA?

Abbiamo già discusso di alcuni dei problemi che hanno spinto alla creazione di WAI-ARIA, ma essenzialmente ci sono 4 grandi aree in cui WAI-ARIA è utile: 

  1. Indicatori/riferimenti: gli attributi role funzionano come descrizioni che possono replicare il valore semantico degli elementi HTML5 (per esempio <nav>), oppure andare oltre HTML5 e funzionare come indicatori che descrivono differenti aree funzionali, per esempio search, tabgroup, tab, listbox, etc.
  2. Aggiornamento dinamico del contenuto: i lettori di schermo in generale hanno difficoltà a indicare quando il contenuto subisce cambiamenti; con ARIA possiamo usare aria-live per indicare agli utenti che usano lettori di schermo quando un' area del contenuto viene aggiornata, per esempio tramite XMLHttpRequest, o DOM APIs .
  3. Migliorare l'accessibilità da tastiera: ci sono elementi HTML che hanno accessibilità da tastiera nativa; quando però invece di usare tali elementi se ne usano altri che li "simulano" in combinazione con JavaScript, l'accessibilità da tastiera e la qualità di lettura dei lettori di schermo ne risentono. In questi casi possiamo usare WAI-ARIA per dare focus a tali elementi  (usando tabindex).
  4. Accessibilità dei controlli non semantici: quando si usano una serie di <div> annidati in combinazione con CSS/JavaScript per creare una funzionalità IU particolarmente complessa, oppure quando un controllo nativo viene notevolmente modificato tramite JavaScript, l'accessibilità può esserne danneggiata. Gli utenti che usano lettori di schermo troveranno difficile capire come funzionano gli elementi se non ci sono indicazioni semantiche che lo spieghino. In situazioni come queste la tecnologia ARIA può aiutare a fornire le indicazioni necessarie tramite una combinazione di ruoli come button, listbox, o tabgroup, e proprietà come aria-requiredaria-posinset.

Ricorda: dovresti ricorrere a WAI-ARIA solo quando è necessario! Idealmente, dovresti usare sempre funzionalità HTML native per fornire le indicazioni semantiche necessarie ai lettori di schermo per interpretare correttamente il contesto. A volte però ciò non è possibile, forse perchè non hai pieno controllo sul codice, o perchè stai creando qualcosa di particolarmente complesso, che non puoi implementare con un elemento HTML standard. In tali casi, WAI-ARIA può essere un utile strumento di miglioramento dell'accessibilità. 

Ma ricorda, usala solo quando è necessario!

Nota: cerca di testare il tuo sito con la maggior varietà possibile di utenti reali: persone non disabili, persone che usano lettori di schermo, persone che navigano con la tastiera, ecc. Queste persone sapranno indicarti cosa funziona e cosa no in maniera molto più accurata di ciò che può emergere limitandoti ad effettuare test di utilizzo personalmente.

Esempi di uso pratico di WAI-ARIA 

Nella prossima sezione analizzeremo le 4 aree più dettagliatamente, e forniremo alcuni esempi pratici. Prima di continuare, dovresti attivare un lettore di schermo, per poter testare alcuni degli esempi.

Vedi la sezione (in inglese) sul testing con lettori di schermo per maggiori informazioni.

Indicatori/riferimenti

WAI-ARIA trasmette l'attributo role ai browser, che permette di aggiungere valore semantico extra agli elementi del tuo sito dovunque sia necessario. La principale utilità di questo attributo è che permette agli utenti che usano lettori di schermo di individuare più facilmente gli elementi più comuni delle pagine. Vediamo un esempio:  il nostro sito senza ruoli (vedi la versione live) ha la seguente struttura:
 

<header>
  <h1>...</h1>
  <nav>
    <ul>...</ul>
    <form>
      <!-- search form  -->
    </form>
  </nav>
</header>

<main>
  <article>...</article>
  <aside>...</aside>
</main>

<footer>...</footer>

Se provi a navigare il sito con un lettore di schermo in un browser moderno, riceverai diverse informazioni utili. Per esempio, VoiceOver fornisce le seguenti indicazioni:

  • Riguardo l'elemento <header> — "banner, 2 oggetti" (contiene un heading h1 e la barra di navigazione <nav>).
  • Riguardo l'elemento <nav> — "navigazione 2 oggetti" (contiene una lista e un campo di ricerca).
  • Riguardo l'elemento <main> — "principale 2 oggetti" (contiene un articolo e una barra di navigazione laterale).
  • Riguardo l'elemento <aside> — "complementario 2 oggetti" (continene un heading h2 e una lista).
  • Riguardo il campo di ricerca — "Funzione ricerca,  casella di testo".
  • Riguardo l'elemento <footer> — "pié di pagina 1 oggetto".

Se ti rechi nella sezione Rotore di VoiceOver (premendo VO-U), vedrai che la maggior parte degli elementi più importanti sono elencati ordinatamente e si può accedere ad essi rapidamente.

Ma in realtà, la situazione è migliorabile. Il campo di ricerca è un punto di riferimento importante che gli utenti vorranno trovare, ma non compare nella lista degli elementi e non è trattato come un elemento di riferimento, a parte l'indicazione che si tratta di una casella di ricerca (<input type="search">). Inoltre, alcuni browser più vecchi (per esempio IE8), non riconoscono le indicazioni semantiche degli elementi HTML5. 

Possiamo migliorare il tutto usando alcune funzionalità ARIA. Per prima cosa aggiungiamo alcuni attributi di ruolo alla nostra struttura HTML. Il nostro esempio di sito con ruoli aria (vedi la versione live) ha la seguente struttura:

<header>
  <h1>...</h1>
  <nav role="navigation">
    <ul>...</ul>
    <form role="search">
      <!-- search form  -->
    </form>
  </nav>
</header>

<main>
  <article role="article">...</article>
  <aside role="complementary">...</aside>
</main>

<footer>...</footer>

C'è anche una funzionalità bonus in questo esempio: all'elemento <input> è stato assegnato l'attributo aria-label, che fornisce ai lettori di schermo una etichetta descrittiva, anche se non abbiamo incluso un elemento <label>. In casi come questo è molto utile usare lattributo ARIA. Un campo di ricerca è infatti un elemento molto comune e facilmente riconoscibile, e aggiungere una etichetta visuale potrebbe danneggiare il disegno della pagina.

<input type="search" name="q" placeholder="Scrivi qui ciò che vuoi cercare" aria-label="Campo per cercare nel contenuto del sito">

Se ora usiamo VoiceOver per leggere il sito d'esempio, notiamo alcuni miglioramenti:

  • Il campo di ricerca viene indicato come un elemento separato, sia mentre si naviga la pagina sia nella sezione Rotore.
  • Il testo contenuto nell'attributo aria-label viene letto quando il campo riceve focus.

Inoltre, il sito è ora maggiormente accessibile per utenti che navigano con browser antiquati come IE8; vale la pena includere ruoli ARIA anche per questo. E se per caso il tuo sito è stato costruito usando solo elementi <div>, dovresti decisamente includere i ruoli ARIA per fornire le necessarie semantiche!

Il valore semantico migliorato del campo di ricerca ha mostrato cosa è possibile fare quando ARIA va oltre le semantiche disponibili con HTML5. Potrai sapere molto di più sulle semantiche e il potere delle proprietà/attributi ARIA qui sotto, specialmente nella sezione Accessibilità dei controlli non semantici. Per ora, vediamo come ARIA ci può aiutare a gestire gli aggiornamenti del contenuto dinamico.

Aggiornamenti del contenuto dinamico

Il contenuto caricato nel DOM può essere facilmente interpretato usando un lettore di schermo, dal contenuto testuale fino al testo alternativo delle immagini. I tradizionali siti statici con contenuto largamente testuale sono dunque facili da rendere accessibili alle persone con deficit visivo.

Il problema è che le applicazioni web moderne spesso non sono composte da testo statico, di solito hanno una gran quantità di contenuto che si aggiorna dinamicamente, cioè contenuto che si agigorna senza che l'intera pagina si ricarichi, tramite meccanismi come XMLHttpRequest, Fetch, o DOM APIs. Queste aree del contenuto sono talvolta chiamate live regions.

Consideriamo un esempio, vedi aria-no-live.html (vedi anche la versione live). In questo esempio troviamo un paragrafo contenente una citazione selezionata casualmente:

<section>
  <h1>Random quote</h1>
  <blockquote>
    <p></p>
  </blockquote>
</section>

JavaScript carica tramite XMLHttpRequest un file JSON contenente una serie di citazioni selezionate casualmente e il rispettivo autore. Quando la citazone è stata caricata, si attiva un loop setInterval() che carica una nuova citazione nel paragrafo ogni 10 secondi:

var intervalID = window.setInterval(showQuote, 10000);

Questo sistema funziona correttamente , ma non è ottiamle per l'accessibilità. Gli aggiornamenti del contenuto non sono rilevati dai lettori di schermo, e g li utenti che li usano non si renderebbero conto di ciò che sta succedendo. Questo esempio è molto basico, ma prova a immaginare cosa succederebbe se stessi creando una IU complessa con molte aree del contenutto che si aggiornano costantemente, come una chat room, un gioco strategico oppure un carrello della spesa che si aggiorna con i prodotti selezionati dall'utente. Sarebbe impossibile usare l'applicazione senza un sistema che avverta gli utenti degli aggiornamenti del contenuto.

Fortunatamente WAI-ARIA ci mette a disposizione un utile meccanismo per fornire tali avvertimenti, la proprietà aria-live. Applicarla a un elemento fa si che i lettori di schermo leggano il contenuto che viene aggiornato. Con quanta frequenza il contenuto viene letto dipende dal valore assegnato:

  • off: valore di default. Gli aggiornamenti non vengono annunciati.
  • polite: gli aggiornamenti vengono annunciati solo quando l'utente è inattivo.
  • assertive: gli aggiornamenti vengono annunciati all'utente il prima possibile.
  • rude: gi aggiornamenti vengono annunciati istantaneamente, anche se facendo ciò si interrompe l'utente.

Generalmente, assegnare il valore assertive è sufficiente perchè gli aggiornamenti vengano annunciati in tempo reale, anche se nel caso di aggiornamenti di multiple aree di contenuto che avvengono allo stesso tempo i vari aggiornamenti saranno annunciati in sequenza, quindi con la possibilità di un breve ritardo sul tempo reale. Si raccomanda di usare rude solo per aggiornamenti ad alta priorità che devono "passare davanti" agli altri aggiornamenti in corso.

Prova a realizzare una copia di aria-no-live.htmlquotes.json, e modificare l'etichetta <section> così:

<section aria-live="assertive">

D'ora in poi il lettore di schermo leggerà il contenuto ogni volta che sarà aggiornato.

Nota: : la maggior parte dei browser attiverà una security exception se provi ad effettuare un XMLHttpRequest da un URL file://. Per esempio se carichi il file direttamente nel browser (con un doppio click ecc.). Per farlo funzionare, devi caricare il file a un server, per esempio usando GitHub (articolo in inglese), o un server locale come Python's SimpleHTTPServer (articolo in inglese).

C'è però una considerazione da tenere in conto: il lettore di schermo legge solo la parte del testo che viene aggiornata. È utile dunque che legga anche l'heading, per aiutare l'utente a ricordare cosa viene letto. Per farlo, possiamoaggiungere la proprietà aria-atomic alla sezione. Modifica la tua etichetta <section> così:

<section aria-live="assertive" aria-atomic="true">

L'attributo aria-atomic="true" indica al lettore di schermo che deve leggere l'intero contenuto dell'elemento, non solo le parti che sono state aggiornate.  

Nota: : puoi vedere l'esempio completo qui: aria-live.html (vedi anche la versione live).

Nota: : la proprietà aria-relevant è utile per controllare cosa viene letto quando un'area di contenuto viene aggiornata. Per esempio puoi far si che siano lette solo le parti aggiunte o al contrario le parti rimosse dal contenuto.

Migliorare l'accessibilità da tastiera

Come abbiamo già detto in altri articoli di questo modulo, uno dei punti forti dell'accessibilità di HTML è che implementa automaticamente l'accessibilità da tastiera per funzionalità come i bottoni, i campi dei formulari e i link. In generale, puoi sempre usare il tasto TAB per muoverti da un elemento all'altro e il tasto ENTER/RETURN per selezionare o attivare gli elementi. In alcune circostanze puoi anche usare altri controlli (per esempio le frecce per muoversi su e giù tra le opzioni di una lista <select>.

Ciononostante, a volte ti troverai a dover scrivere codice che fa uso di elementi non semantici con funzione di bottoni(o altri tipi di elementi), o usa elementi che possono ricevere focus per scopi diversi dal normale. Forse starai cercando di sistemare del codice mal scritto in precedenza, o di costruire un qualche tipo di widget complesso che richiede tecniche non ortodosse.

Per rendere focalizzabili elementi che normalmente non lo sono, WAI-ARIA estende l'attributo tabindex con alcuni nuovi valori:

  • tabindex="0" — come specificato in precedenza, questo valore rende "tabbabili" elementi che normalmente non lo sono. Questo è il valore più utile di tabindex.
  • tabindex="-1" — questo valore permette ad elementi normalmente non tabbabili di ricevere focus programmaticamente, per esempio tramite JavaScript, o come destinazione di un link. 

Abbiamo discusso questi valori in maggior dettaglio e mostrato una implementazione tipica nel nostro articolo sull'accessibilità in HTML, vedi Implementare l'accessibilità da tastiera in un secondo tempo.

Accessibility of non-semantic controls

This follows on from the previous section — when a series of nested <div>s along with CSS/JavaScript is used to create a complex UI-feature, or a native control is greatly enhanced/changed via JavaScript, not only can keyboard accessibility suffer, but screenreader users will find it difficult to work out what the feature does if there are no semantics or other clues. In such situations, ARIA can help to provide those missing semantics.

Form validation and error alerts

First of all, let's revisit the form example we first looked at in our CSS and JavaScript accessibility article (read Keeping it unobtrusive for a full recap). At the end of this section we showed that we have included some ARIA attributes on the error message box that apears when there are validation errors when you try to submit the form:

<div class="errors" role="alert" aria-relevant="all">
  <ul>
  </ul>
</div>
  • role="alert" automatically turns the element it is applied to into a live region, so changes to it are read out; it also semantically identifies it as an alert message (important time/context sensitive information), and represents a better, more accessible way of delivering an alert to a user (modal dialogs like alert() calls have a number of accessibility problems; see Popup Windows by WebAIM).
  • An aria-relevant value of all instructs the screenreader to read out the contents of the error list when any changes are made to it — i.e. when errors are added or removed. This is useful because the user will want to know what errors are left, not just what has been added or removed from the list.

We could go further with our ARIA usage, and provide some more validation help. How about indicating whether fields are required in the first place, and what range the age should be?

  1. At this point, take a copy of our form-validation.html and validation.js files, and save them in a local directory.
  2. Open them both in a text editor and have a look at how the code works.
  3. First of all, add a paragraph just above the opening <form> tag, like the one below, and mark both the form <label>s with an asterisk. This is normally how we mark required fields for sighted users.
    <p>Fields marked with an asterisk (*) are required.</p>
  4. This makes visual sense, but it isn't as easy to understand for screenreader users. Fortunately, WAI-ARIA provides the aria-required attribute to give screenreaders hints that they should tell users that form inputs need to be filled in. Update the <input> elements like so:
    <input type="text" name="name" id="name" aria-required="true">
    
    <input type="number" name="age" id="age" aria-required="true">
  5. If you save the example now and test it with a screenreader, you should hear something like "Enter your name star, required, edit text".
  6. It might also be useful if we give screenreader users and sighted users an idea of what the age value should be. This is often presented as a tooltip, or placeholder inside the form field perhaps. WAI-ARIA does include aria-valuemin and aria-valuemax properties to specify min and max values, but these currently don't seem very well supported; a better supported feature is the HTML5 placeholder attribute, which can contain a message that is shown in the input when no value is entered, and is read out by a number of screenreaders. Update your number input like this:
    <input type="number" name="age" id="age" placeholder="Enter 1 to 150" aria-required="true">

Note: You can see the finished example live at form-validation-updated.html.

WAI-ARIA also enables some advanced form labelling techniques, beyond the classic <label> element. We already talked about using the aria-label property to provide a label where we don't want the label to be visible to sighted users (see the Signposts/Landmarks section, above). There are some other labelling techniques that use other properties such as aria-labelledby if you want to designate a non-<label> element as a label or label multiple form inputs with the same label, and aria-describedby, if you want to associate other information with a form input and have it read out as well. See WebAIM's Advanced Form Labeling article for more details.

There are many other useful properties and states too, for indicating the status of form elements. For example, aria-disabled="true" can be used to indicate that a form field is disabled. Many browsers will just skip past disabled form fields, and they won't even be read out by screenreaders, but in some cases they will be perceived, so it is a good idea to include this attribute to let the screenreader know that a disabled input is in fact disabled.

If the disabled state of an input is likely to change, then it is also a good idea to indicate when it happens, and what the result is. For example, in our form-validation-checkbox-disabled.html demo there is a checkbox that when checked, enables another form input to allow further information be entered. We've set up a hidden live region:

<p class="hidden-alert" aria-live="assertive"></p>

which is hidden from view using absolute positioning. When this is checked/unchecked, we update the text inside the hidden live region to tell screenreader users what the result of checking this checkbox is, as well as updating the aria-disabled state, and some visual indicators too:

function toggleMusician(bool) {
  var instruItem = formItems[formItems.length-1];
  if(bool) {
    instruItem.input.disabled = false;
    instruItem.label.style.color = '#000';
    instruItem.input.setAttribute('aria-disabled', 'false');
    hiddenAlert.textContent = 'Instruments played field now enabled; use it to tell us what you play.';
  } else {
    instruItem.input.disabled = true;
    instruItem.label.style.color = '#999';
    instruItem.input.setAttribute('aria-disabled', 'true');
    instruItem.input.removeAttribute('aria-label');
    hiddenAlert.textContent = 'Instruments played field now disabled.';
  }
}

Describing non-semantic buttons as buttons

A few times in this course already, we've mentioned the native accessibilty of (and the accessibility issues behind using other elements to fake) buttons, links, or form elements (see UI controls in the HTML accessibility article, and Enhancing keyboard accessibility, above). Basically, you can add keyboard accessibility back in without too much trouble in many cases, using tabindex and a bit of JavaScript.

But what about screenreaders? They still won't see the elements as buttons. If we test our fake-div-buttons.html example in a screenreader, our fake buttons will be reported using phrases like "Click me!, group", which is obviously confusing.

We can fix this using a WAI-ARIA role. Make a local copy of fake-div-buttons.html, and add role="button" to each button <div>, for example:

<div data-message="This is from the first button" tabindex="0" role="button">Click me!</div>

Now when you try this using a screenreader, you'll have buttons be reported using phrases like "Click me!, button" — much better.

Note: Don't forget however that using the correct semantic element where possible is always better. If you want to create a button, and can use a <button> element, you should use a <button> element!

Guiding users through complex widgets

There are a whole host of other roles that can identify non-semantic element structures as common UI features that go beyond what's available in standard HTML, for example combobox, slider, tabpanel, tree. You can see a number of userful examples in the Deque university code library, to give you an idea of how such controls can be made accessible.

Let's go through an example of our own. We'll return to our simple absolutely-positioned tabbed interface (see Hiding things in our CSS and JavaScript accessibility article), which you can find at Tabbed info box example (see source code).

This example as-is works fine in terms of keyboard accessibility — you can happily tab between the different tabs and select them to show the tab contents. It is also fairly accessible too — you can scroll through the content and use the headings to navigate , even if you can't see what is happening on screen. It is however not that obvious what the content is — a screenreader currently reports the content as a list of links, and some content with three headings. It doesn't give you any idea of what the relationship is between the content. Giving the user more clues as to the structure of the content is always good.

To improve things, we've created a new version of the example called aria-tabbed-info-box.html (see it running live). We've updated the structure of the tabbed interface like so:

<ul role="tablist">
  <li class="active" role="tab" aria-selected="true" aria-setsize="3" aria-posinset="1" tabindex="0">Tab 1</li>
  <li role="tab" aria-selected="false" aria-setsize="3" aria-posinset="2" tabindex="0">Tab 2</li>
  <li role="tab" aria-selected="false" aria-setsize="3" aria-posinset="3" tabindex="0">Tab 3</li>
</ul>
<div class="panels">
  <article class="active-panel" role="tabpanel" aria-hidden="false">
    ...
  </article>
  <article role="tabpanel" aria-hidden="true">
    ...
  </article>
  <article role="tabpanel" aria-hidden="true">
    ...
  </article>
</div>

Note: The most striking change here is that we've removed the links that were originally present in the example, and just used the list items as the tabs — this was done because it makes things less confusing for screenreader users (the links don't really take you anywhere; they just change the view), and it allows the setsize/position in set features to work better — when these were put on the links, the browser kept reporting "1 of 1" all the time, not "1 of 3", "2 of 3", etc.

The new features are as follows:

  • New roles — tablist, tab, tabpanel — these identify the important areas of the tabbed interface — the container for the tabs, the tabs themselves, and the corresponding tabpanels.
  • aria-selected — Defines which tab is currently selected. As different tabs are selected by the user, the value of this attribute on the different tabs is updated via JavaScript.
  • aria-hidden — Hides an element from being read out by a screenreader. As different tabs are selected by the user, the value of this attribute on the different tabs is updated via JavaScript.
  • tabindex="0" — As we've removed the links, we need to give the list items this attribute to provide it with keyboard focus.
  • aria-setsize — This property allows you to specify to screenreaders that an element is part of a series, and how many items the series has.
  • aria-posinset — This property allows you to specify what position in a series an element is in. Along with aria-setsize, it provides a screenreader with enough information to tell you that you are currently on item "1 of 3", etc. In many cases, browsers should be able to infer this information from the element hierarchy, but it certainly helps to provide more clues.

In our tests, this new structure did serve to improve things overall. The tabs are now recognised as tabs (e.g. "tab" is spoken by the screenreader), the selected tab is indicated by "selected" being read out with the tab name, and the screenreader also tells you which tab number you are currently on. In addition, because of the aria-hidden settings (only the non-hidden tab ever has aria-hidden="false" set), the non-hidden content is the only one you can navigate down to, meaning the selected content is easier to find.

Note: If there is anything you explicitly don't want screen readers to read out, you can give them the aria-hidden="true"  attribute.

Summary

This article has by no means covered all that's available in WAI-ARIA, but it should have given you enough information to understand how to use it, and know some of the most common patterns you will encounter that require it.

See also

Tag del documento e collaboratori

 Hanno collaborato alla realizzazione di questa pagina: mipo
 Ultima modifica di: mipo,