No. 101

Titolo originale: ARIA and Progressive Enhancement

Pubblicato in: Accessibilità

Scritto da Derek Featherstone

Per sette anni, ci siamo aggrappati saldamente alla convinzione che l'uso del progressive enhancement fosse il modo corretto di costruire siti web ed applicazioni. Il progressive enhancement è il modo in cui costruiamo soluzioni web sostenibili, interoperabili ed accessibili.

Ci siete già passati:

  1. iniziate dall'HTML semantico puro,
  2. fornite un layer di indicazioni di presentazione per mezzo di CSS (che possono o meno essere sovrascritte dagli stili dell'utente) e
  3. fornite un layer di miglioramenti del comportamento con JavaScript (che ancora una volta, possono o meno essere sovrascritti o integrati dagli script dell'utente).

Ad ogni tappa durante il viaggio, abbiamo quello che equivale ad una soluzione funzionante. Costruiamo ogni soluzione funzionante in cima ad altre già soluzioni funzionanti.

Ora che il rilascio di ARIA si avvicina, diamo uno sguardo a come ARIA si inserisce all'interno della strategia del progressive enhancement. Possiamo usare ARIA in una maniera che rispetti il progressive enhancement? Possiamo usare ARIA in qualche modo che garantisca di avere una soluzione funzionante ad ogni livello?

ARIA semplificata

ARIA è una specifica emergente del W3C ed è un impegno verso l'accessibilità supportato da un certo numero di aziende. ARIA è pensata per fornire l'accessibilità ad un livello tecnico, che si potrebbe definire “accessibilità programmatica”, dove non esiste ancora. Ad esempio, molti date picker e altre widget avanzate che aggiungiamo ai nostri siti web non sono nulla di più di una collezione di elementi <div> e <span> senza alcun valore semantico: ARIA cerca di dare quel significato semantico.

Dovete tenere a mente che ARIA non è ancora del tutto ultimata: al momento in cui scrivo, è pubblicata come “working draft” ed è oggetto di revisione. Questo è il modo in cui funzionano le specifiche. Infatti, se leggete l'articolo del 2007 di Martin Kliehm sul numero 235 di ALA, Accessible Web 2.0 Applications with WAI-ARIA [Applicazioni Web 2.0 Accessibili con WAI-ARIA, ndt] , noterete che molte cose sono cambiate. I concetti generali di ARIA sono ancora gli stessi, ma l'implementazione attuale è molto più semplice e sarà molto più facile da usare.

Alla fine, implementare ARIA nei vostri progetti ci permetterà di dire in maniera affidabile alle tecnologie assistive “questo div è in realtà una dialog box” oppure “questa lista ordinata di link è in realtà un menu con le varie scelte” o “questa collezione di div, immagini e span è una progress bar e questa progress bar al momento si trova al 75%”.

ARIA mette a disposizioni tre mezzi per fare ciò. Ci permettono di comunicare:

  • quale ruolo abbia un particolare componente nell'interfaccia,
  • le proprietà di quel componente e
  • lo stato attuale di quel componente.

Tutto questo si può fare usando gli attributi e i valori di ARIA proprio come usiamo qualunque altro attributo e valore HTML, ma li modifichiamo utilizzando degli script in risposta agli eventi che accadono all'interno del browser. Parte di quello che fornisce ARIA aiuta anche a stabilire delle relazioni programmatiche tra parti dell'interfaccia, ma lasciamo questa parte per dopo.

ARIA in the wild

Abbiamo recentemente rilanciato Simply Accessible, un sito in cui raccogliamo tutti i nostri scritti riguardanti l'accessibilità. Nel codice del sito abbiamo utilizzato gli ARIA landmark roles per fornire un insieme standardizzato di navigational landmarks [punti di riferimento per la navigazione della pagina, ndt] all'interno della pagina. Se guardate una pagina campione contenente un articolo, come ad esempio Custom Stylesheets for iOS ["Fogli di stile personalizzati per iOS", ndt], noterete che le pagine contenenti un articolo hanno le seguenti definizioni di landmark roles all'interno del codice:

  • role="banner" per lo header del sito,
  • role="navigation" per ogni menu di navigazione sia in alto sia in basso nella pagina,
  • role="search" per la form di ricerca,
  • role="main" per il contenuto principale della pagina,
  • role="complementary" per le informazioni contenute nella sidebar e
  • role="contentinfo" per la dichiarazione di copyright in fondo alla pagina.

Questo codice fa in modo che le tecnologie assistive che comprendono gli ARIA landmarks si possano spostare da un landmark all'altro usando degli shortcuts da tastiera (come succede con lo screen reader JAWS) o delle gestures (come con VoiceOver di Apple).

Ecco un altro esempio di ARIA in azione: A slider widget on a Google Map ["Una widget slider su una mappa di Google Maps", ndt]. In questa implementazione di una mappa di Google Maps, abbiamo aggiunto ARIA allo slider che permette di cambiare i livelli di zoom. Abbiamo aggiunto ARIA a questo elemento piuttosto semplicemnte per non c'è un elemento nativo di HTML per lo slider: dobbiamo costruircelo con gli attrezzi che abbiamo a disposizione. Quindi, per approssimare un vero slider che potreste vedere a livello di sistema operativo, abbiamo aggiunto ARIA al markup HTML di base. Qui abbiamo:

  1. indicato un ruolo per il componente (role="slider"),
  2. usato aria-orientation="vertical" per specificare che è …suspense… orientato verticalmente e
  3. aggiunto molte proprietà a tale slider (aria-valuemin="0", aria-valuemax="17", aria-valuetext="14" e aria-valuenow="14").

Scorrendo lungo lo slider per cambiare il livello di zoom, usiamo JavaScript per cambiare il valore di aria-valuenow e aria-valuetext per farlo corrispondere al valore di zoom.

Vengono mostrati aria-valuetext e aria-valuenow con il valore impostato a 12

Fig 1. Vengono mostrati aria-valuetext e aria-valuenow con il valore di 12.

Potete verificare questa cosa voi stessi usando Firebug o un altro developer tool. La Figura 1 mostra aria-valuetext e aria-valuenow evidenziati al valore 12, che corrisponde al livello dello zoom della mappa. Quando JavaScript è attivato, quei valori si aggiornano dinamicamente mentre fate lo zoom avanti o indietro. Per un vero progressive enhancement, dovrete creare una versione che utilizzi un form in cui selezionare il livello di zoom ed utilizzare la Google Maps Static API, che non richiede JavaScript.

In utilizzi tipici di ARIA come questi:

  1. i role attributes semplici di ARIA definiscono il ruolo delle varie parti della pagina: role="menu", role="dialog", role="navigation" e role="tablist",
  2. le proprietà semplici di ARIA definiscono una connessione tra le varie componenti dell'interfaccia: aria-labelledby="someid", aria-describedby="anotherid", aria-haspopup="true" e
  3. gli stati semplici di ARIA definiscono lo stato attuale degli oggetti nella pagina: aria-hidden="true", aria-invalid="false", aria-disabled="true", aria-expanded="false".

Andate direttamente alla sorgente per tutti i dettagli su qualunque ARIA roles e sugli stati e le proprietà.

Per usare ARIA, abbiamo bisogno che molti pezzi del puzzle vadano a posto. Come avete visto nell'esempio dello slider, abbiamo bisogno di aggiungere gli attributi ARIA al nostro HTML per poi controllarli tramite JavaScript mentre la pagina si aggiorna dinamicamente.

Tuttavia, il supporto per ARIA non è così semplice. Sì, possiamo aggiungere ARIA per aggiungere dello “zucchero semantico,” ma c'è dell'altro.

L'accessibilità richiede che tutti, autori e creatori di contenuto, produttori di browser, produttori di tecnologie assistive e persone che usano il sito o l'app, devono sedersi ad un tavolo e avere gli attrezzi giusti.

Quali sono gli attrezzi giusti per ARIA?

Alcuni browser supportano in parte ARIA. Le attuali versioni di Firefox 3, Opera 9.5+, IE 8/9 e dei browser basati su WebKit come Safari 4+ supportano tutte alcuni aspetti di ARIA. Di sicuro, il loro supporto non è completo. Non può esserlo semplicemente perché la specifica non è stata ancora completata.

Alcune tecnologie assistive supportano in qualche maniera ARIA. Le attuali versioni di JAWS, Window-Eyes, NVDA, VoiceOver e ZoomText supportano parzialmente ARIA, ma le versioni precedenti, ovviamente, no.

Il momento della verità

Un modo veramente semplice per cominciare ad implementare ARIA consiste nell'utilizzare il concetto di “landmark role”.

L'avete già visto se avete guardato il nostro sito Simply Accessible. Ma ci sono altre piccole cose che vanno evidenziate riguardo il progressive enhancement.

Diamo un'occhiata ad un esempio: il role “navigation”.

Ecco come abbiamo programmato la navigazione nelle sezioni <footer> e <header> del sito.

 
<nav role="navigation">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/archives/">Archives</a></li>
    <li><a href="/about/">About</a></li>
    <li><a href="/contact/">Contact</a></li>
  </ul>
</nav> 
 

Probabilmente vi state chiedendo: “Perché mai c'è un ruolo “navigation” su un elemento chiamato <nav>?” E se non ve lo state chiedendo, dovreste. Queste domande sono quelle che dovrete affrontare sempre progredendo con ARIA.

Ecco il punto: ARIA è solo parzialmente supportata dai browser e dalle tecnologie assistive. Analogamente, abbiamo usato l'elemento <nav> di HTML5, che, come potrete aspettarvi, è supportato solo parzialmente dai browser e dalle tecnologie assistive. Possiamo usare un elemento chiamato <nav> ed i browser lo gestiranno ragionevolmente bene, ma non ci fanno nulla di utile, come passarlo alle API di accessibilità del sistema operativo. Senza un supporto significativo, <nav> potrebbe benissimo essere un <div>.

Questo vuol dire che mentre <nav> può avere degli stili e verrà reso in un browser, proprio ora, non c'è nulla che indichi ad uno screen reader o a qualunque altra tecnologia assistiva che questo elemento all'interno della pagina deve essere usato per la navigazione. Tuttavia, alcune tecnologie assistive riconoscono role="navigation" come un landmark role. Così, l'abbiamo raddoppiato e aggiunto un role="navigation" all'elemento <nav>.

E cosa succede in uno scenario in cui né <nav> di HTML5 né role="navigation" di ARIA sono supportati? All'interno di <nav> usiamo la nostra fedele lista non ordinata i cui elementi sono gli elementi della navigazione, le liste che abbiamo usato per anni per la navigazione.

Ora diamo uno sguardo ad un esempio un po' più complicato: specificare i campi obbligatori di una form.

Andare in fondo alla questione

Un vantaggio del markup ARIA è che saremo un giorno in grado di comunicare alla svelta i campi obbligatori alle tecnologie assistive ad un livello programmatico:

 
<label for="firstname">First Name</label>
<input type="text" id="firstname" aria-required="true" />
 

In definitiva questo vuol dire che un utente di screen reader sentirà: “First Name, type in text, required.” [“Nome, inserire del testo, obbligatorio”, ndt].

Potremmo anche usare delle regole CSS per fornire dei suggerimenti basati su questo attributo:

 
input[aria-required=true]:after {
    content("(required)");
}
 

Sappiamo che ARIA è supportata parzialmente dalle tecnologie assistive, ma come verrà reso questo esempio proprio adesso? Il contenuto generato non viene letto dalle attuali versioni di JAWS e WindowEyes, ma viene letto da VoiceOver di APPLE. Tuttavia, non possiamo farvi affidamento e questo contenuto generato a sua volta fa affidamento su un selettore di attributo che è supportato o può non essere supportato dal vostro browser. E cosa succede con gli screen reader che non supportano ARIA?

Il problema è che se fate affidamento su ARIA per comunicare l'attributo obbligatorio agli screen reader, tale stato non sarà comunicato alle tecnologie assistive che non comprendono ARIA.

Per risolvere questo problema, abbiamo bisogno di fornire un altro meccanismo per comunicare lo stato obbligatorio senza usare ARIA.

“Aspetta un attimo!” direte. “Possiamo usare l'attributo required di HTML5!”

Sì, potreste usare l'attributo required di HTML5, ma di nuovo, funzionerà solo dove HTML5 è supportato ed esposto all'API di accessibilità. In quel caso, abbiamo bisogno di un altro metodo per fornire una notifica dei campi obbligatori.

Quindi, prendiamo in considerazione un altro metodo più tradizionale, basato sul lavoro che abbiamo fatto all'inizio del 2005 (vedi Required Form Fields [Campi obbligatori delle form, ndt], in cui assicuriamo che lo stato obbligatorio si codificato come parte del label).

Quando facciamo ciò, forniamo questa informazione a quelle tecnologie assistive in uno stato “non-ARIA”. Ma qual è l'impatto sulle tecnologie assistive che effettivamente comprendono ARIA? Dobbiamo prendere in considerazione molti esempi per capire quali sono le opzioni che abbiamo a disposizione per indicare i campi obbligatori.

Ecco un'analisi passo a passo di alcuni dei nostri test di base. Prima passiamo dallo scenario più semplice: l'attributo required di HTML5.

Ecco un esempio che utilizza l'attributo required di HTML5 per denotare il campo obbligatorio:

 
<label for="username">User Name</label>
<input type="text" id="username" required />
 

Ci sono grandi speranze riguardo a questa soluzione, ma al momento in cui scrivo, questo attributo non è esposto a nessuna delle tecnologie assistiva che usiamo per i test. Lo stato obbligatorio non viene in alcun modo dichiarato usando JAWS 11, Window-Eyes 7.2, NVDA, VoiceOver o ZoomText. Semplicemente, il supporto per l'attributo required di HTML5 non c'è ancora, pertanto dobbiamo trovare un'altra soluzione.

Un altro semplice metodo sarebbe quello di usare solo ARIA per denotare il campo obbligatorio:

 
<label for="username">User Name</label>
<input type="text" id="username" aria-required="true" />
 

In questo caso, JAWS 11, Window-Eyes 7, NVDA e ZoomText hanno tutti supportato ed annunciato che il campo era obbligatorio. VoiceOver sul Mac non ha annunciato che il campo era richiesto, a causa di un bug che sarà probabilmente sistemato in un aggiornamento di VoiceOver. C'è abbastanza supporto per questa tecnica per considerarla valida a questo stadio.

Guardiamo lo scenario non-ARIA così da avere il quadro completo.

Ecco un esempio che usa sia ARIA sia il nostro metodo tradizionale “in-the-label” per quegli scenari in cui ARIA non è supportata.

 
<label for="username">User Name <em>(required)</em></label>
<input type="text" id="username" aria-required="true" />
 

In questo caso, JAWS 11, Window-Eyes 7, NVDA e ZoomText hanno tutti annunciato che il campo era richiesto per due volte. E' certamente meglio che lo scenario in cui non veniva annunciato per niente, ma vorremmo davvero ridurre la ripetizione per rendere quanto più semplice possibile la comprensione. VoiceOver non riconosce il testo “required” nella label perché è inserito all'interno dell'elemento <em> (un risultato dello stesso bug citato prima) e quindi la versione attuate di VoiceOver non legge il testo “required” quando si trova in modalità form.

Proviamo a ridurre quella ripetizione presente nel nostro metodo tradizionale “in-the-label” e role="presentation" così che quando ARIA sarà supportata il contenuto di <em> non venga letto:

 
<label for="username">User Name
   <em role="presentation">(required)</em>
</label>
 
<input type="text" id="username" aria-required="true" />
 

In questo caso, JAWS 11, Window-Eyes 7, NVDA e ZoomText hanno tutti annunciato due volte che il campo era obbligatorio.

Davvero?

Sì, davvero. Il problema qui sta nel funzionamento di role="presentation". E' progettato in modo tale che quando role="presentation" viene aggiunto ad un nodo, dice alla tecnologia assistiva di ignorare la semantica di quel nodo, ma questo non si applica ai nodi figli, inclusi i nodi di testo. Bleh. Questo a me sembra tutt'altro che intuitivo, ma è una realtà con cui dobbiamo fare i conti. Sorprendentemente, VoiceOver funziona correttamente in questo caso: legge che il campo è obbligatorio, presumibilmente perché role="presentation" sull'elemento <em> gli dice di ignorare la semantica. Questo praticamente espone il contenuto testuale, in maniera tale che “required” viene ora letto da VoiceOver.

Abbiamo perfino provato ad usare ARIA, il nostro tradizionale metodo “in-the-label” e aria-hidden="true", in modo tale che quando ARIA è supportato, il contenuto di <em> non venga letto per evitare le duplicazioni:

 
<label for="username">User Name
   <em aria-hidden="true">(required)</em>
</label>
 
<input type="text" id="username" aria-required="true" />
 

Questo non è il vero utilizzo per cui era stato pensato aria-hidden, era inteso come un modo per esprimere che qualcosa al momento è nascosto (hidden). Ad esempio, se avete un panel o dell'altro contenuto che mostrate e nascondete, dovreste usare aria-hidden="true" quando è nascosto e aria-hidden="false" quando lo si mostra. Tuttavia, la specifica in draft dice quanto segue su aria-hidden:

Gli autori POSSONO, con cautela, usare aria-hidden per nascondere del contenuto reso visivamente dalle tecnologie assistive solo se l'atto di nascondere questo contenuto è inteso per migliorare l'esperienza d'uso per gli utenti di tecnologie assistive riducendo la ridondanza. Gli autori che utilizzano aria-hidden per nascondere agli screen reader del contenuto visibile DEVONO assicurarsi che i medesimi o equivalenti significati e funzionalità siano accessibili alle tecnologie assistive.

Questo sembra perfetto per questa applicazione, non trovate? Stiamo esprimendo un significato equivalente in tutti gli scenari: ARIA e non-ARIA. Il supporto per aria-hidden mancava nei nostri test. In questo caso, JAWS 11, Window-Eyes 7, NDVA e ZoomText annunciano tutti due volte che il campo era obbligatorio. VoiceOver non lo annuncia come obbligatorio nemmeno uno volta quando lo trova nel contenuto di <em> e non lo gestisce in maniera appropriata con aria-hidden="true" su questo elemento figlio della label, sebbene sembra che funzioni con aria-hidden="true" su dell'altro contenuto. Questa tecnica potrebbe rivelarsi utile in futuro, man mano che migliora il supporto per aria-hidden nelle tecnologie assistive.

Questo ci lascia un'ultima opzione (almeno per ora): una per cui non vado matto, ma eccola:

Qui stiamo usando ARIA, il tradizionale metodo “in-the-label” e role="presentation" su un'immagine che ha come testo dell'alt “Required”:

 
<label for="username">User Name
   <img role="presentation" src="/required.png" alt="Required" />
</label>
 
<input type="text" id="username" aria-required="true" />
 

role="presentation" su un'immagine dice ai browser che supportano ARIA e alle tecnologie assistive di ignorare la semantica di quel nodo. Quel nodo ha il testo impostato a “obbligatorio” per alt e nel caso in cui ARIA è supportato viene ignorato.

In quest'ultimo scenario, JAWS 11, Window-Eyes 7, NVDA e ZoomText annunciano tutti che il campo è richiesto, esattamente una sola volta. E nelle versioni più vecchie, in cui ARIA non è supportata o con i browser che potrebbero non comunicare i ruoli e gli attributi di ARIA alle API di accessibilità? Ottengono la versione non-ARIA. In questo caso, VoiceOver non indica che il campo è obbligatorio, molto probabilmente a causa dello stesso bug di cui abbiamo parlato negli altri casi.

Sì, anche a me questo fa venire da piangere. Come se tutto questo non fosse troppo doloroso, ecco un riassunto di questi test in forma tabellare:

ARIA Tests Results
Zoom Text 9.1 JAWS 11 Window-Eyes 7.2 NVDA VoiceOver
HTML5 required Non annuncia che il campo è required [obbligatorio] Non annuncia che il campo è required [obbligatorio] Non annuncia che il campo è required [obbligatorio] Non annuncia che il campo è required [obbligatorio] Non annuncia che il campo è required [obbligatorio]
ARIA required to match other references to ARIA Annuncia “required” una volta Annuncia “required” una volta Annuncia “required” una volta Annuncia “required” una volta Annuncia “required” una volta
required nella label e ARIA required Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte
required nella label e ARIA required, include role="presentation" Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte
required nella label e aria-hidden="true" Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte Annuncia “required” due volte Non annuncia che il campo è required [obbligatorio]
required nella label e ARIA required, include role="presentation" su un'immagine Annuncia “required” una volta Annuncia “required” una volta Annuncia “required” una volta Annuncia “required” una volta Non annuncia che il campo è obbligatorio

Il problema, come lo vedo io

Parte del problema, al momento, consiste nel fatto che non sappiamo quando ARIA sarà supportata. Dobbiamo scoprire gli oggetti e le funzioni prima di poterli usare: se non sono presenti o non sono supportati, dobbiamo essere sicuri di avere ancora una soluzione affidabile da utilizzare. Ma nel caso di ARIA? Non abbiamo tanta fortuna.

Qual è il risultato dell'usare il progressive enhancement tradizionale insieme ad ARIA? Come qualunque altra specifica, quando usiamo una tecnologia, ci aspettiamo, in generare, che sia supportata tutta o almeno la maggior parte di quella specifica. Ad esempio, non usereste mai CSS per i colori di background se non ci fosse anche il supporto per il colore del testo. Lo stesso vale per ARIA: ci aspettiamo ed abbiamo bisogno di fare affidamento sugli user agent e sulle tecnologie assistive per supportare tutti gli aspetti di ARIA. Ad ora, dal momento che la specifica è in dirittura di arrivo e le implementazioni si stanno ancora evolvendo, semplicemente, non l'abbiamo.

Perché questo funzioni, allora, abbiamo bisogno di avere dei modi all'interno di ARIA anche per “spegnere” le cose, per nascondere quelle ridondanze che abbiamo creato utilizzando il progressive enhancement tradizionale insieme ad ARIA.

Come abbiamo visto nell'esempio dei campi obbligatori all'interno di una form, la nostra più rosea speranza al momento è una combinazione di role="presentation" e aria-hidden="true".

Guardiamo un ultimo esempio: un'interfaccia “tabbed panel”.

Senza ARIA, possiamo fare un po' di cose per far sì che il tabbed panel funzioni in tutti gli scenari. Come parte di una strategia di progressive enhancement, dovremmo assicurarci che il contenuto funzioni per prima cosa con le funzionalità di base fornite da HTML. Poi, cambieremo l'aspetto dell'insieme di tab e, in ultima istanza, ne cambieremo il comportamento.

Ecco una strategia di base:

Senza JavaScript, avremmo una lista non ordinata di link in un pagina che puntano ad un punto più in basso nella pagina che contiene il contenuto della tab. Potremmo perfino includere un heading all'inizio del contenuto per aiutare a creare un'associazione.

Ecco una versione base che mostra come verrebbe supportato questo contenuto senza l'uso di JavaScript.

Potete vedere che in alto nella pagina abbiamo un insieme di base di link che puntano al contenuto già presente nella pagina:

 
<ul> 
	<li><a href="#first">First Tab</a></li> 
	<li><a href="#second">Second Tab</a></li> 
	<li><a href="#third">Third Tab</a></li> 
</ul>
 

Questo si prende cura dello scenario non-JS. Ora che funziona senza JavaScript, portiamo questo esempio un po' più in alto, trasformando quella stessa pagina in un insieme di tab. Utilizzando del JavaScript astuto [o scaltro o fatto a mano], creiamo una versione “JavaScript enabled” che applica dei nuovi stili e delle funzionalità specifiche da tastiera.

Con JavaScript attivato, vedrete che i link di base sono trasformati. Utilizziamo questo JavaScript per impostare tutto ciò con la funzione AriaTabs. In pseudo-codice ha questo aspetto:

  1. Fai un loop tra i div che sono utilizzati come tab,
    1. imposta class="tabPanel" così che scelga la regola CSS appropriata e
    2. nascondi il div/tab Panel.
  2. Cerca la tab list (la nostra navigazione) e fai un loop all'interno di ciascuna per,
    1. creare gli appropriati valori degli id per legare i controlli alla tab,
    2. imposta il click per ogni link così che cambi l'attuale tab attivo nella tablist, mostri il contenuto del nuovo tab e nasconda il contenuto del tab precedente,
    3. crea le combinazioni di tasti appropriate per le tab a partire dalla DHTML Style Guide (ne parlerò a breve) e
    4. determina quale tab deve mostrarsi e aggiungi la classe CSS class="current" così che abbia un diverso aspetto rispetto agli altri tab.

Trovate la funzione completa qui.

Questo esempio funziona bene per gli utenti da tastiera e non richiede ARIA per gli utenti di tecnologie assistive. Gli utenti di screen reader cliccheranno sui link che si trovano all'interno della stessa pagina e questo è esattamente quello che ottengono. Giocate un po' con questo esempio e vedrete che potete usare la tastiera per spostare il focus sul controllo tab ed usare le frecce destra e sinistra per spostarvi da un tab all'altro oppure potete usare il tasto tab per spostarvi al tab successivo e premere invio per mostrare il tab.

Questo è un pezzo importante del puzzle: senza ARIA, nessuna di queste verrebbe annunciata alla tecnologia assistiva come tab, quindi rimanere attaccati ai link come ad un paradigma familiare è un passo importante per fare in modo che l'interfaccia abbia senso.

Come passo finale, abbiamo aggiunto il supporto per ARIA aggiungendo gli attributi di ARIA per fornire l'appropriata accessibilità programmatica alle tecnologie assistive.

Usiamo la stessa strategia di base usata senza ARIA, con alcune aggiunte al codice:

  1. Facciamo un loop all'inderno dei singoli tabpanels per:
    1. aggiungere supporto per ARIA assegnando a ciascuno di esse un role="tabpanel" e
    2. lo nascondiamo con aria-hidden="true".
  2. Quando troviamo e creiamo la nostra tab list, le diamo un role="tablist" e facciamo un loop all'interno di ciascun elemento nella tablist per:
    1. assegnargli un role="tab" ed impostare aria-selected="false",
    2. spostarci un livello più su nel DOM verso l'elemento padre ed assegnargli un role="presentation" per eliminare il significato semantico dato da elemento della lista (perché? Nello scenario ARIA, la lista non ha significato perché questa è ora una tablist ARIA),
    3. leghiamo programmaticamente il tab ed il tabpanel con aria-labelledby (pensate a questo come ad una coppia
    4. impostate gli handler dei tasti per cambiare tab, proprio come abbiamo fatto senza ARIA, ma questa volta, non solo manipoliamo le classi CSS, cambiamo gli attributi di ARIA e
    5. aggiungiamo tabindex="-1" ai tab non attivi così che possiamo portare il focus su di essi programmaticamente, ma non sono più nell'ordine di default dei tab.

Trovate la funzione completa qui.

Abbiamo fatto molto in questo caso per impostarlo con ARIA e le appropriate combinazioni di tasti: vi starete tuttavia chiedendo cosa sono le combinazioni di tasti appropriate.

Per tutti i dettagli, fate riferimento alla sezione sui tab panels della AOL DHTML Style Guide. Questo documento cerca di codificare quali comportamenti da tastiera dovrebbero esistere per una varietò di widget all'interno delle pagine web e delle applicazioni.

In poche parole, un tab control (che non si trova nativamente sul web) funziona così: usate il tasto tab per portare il focus sulla list di tab disponibili e il tab al momento attivo ottiene il focus. Usiamo poi le frecce per spostarci tra i tab e di nuovo il tasto tab per lasciare il tabbed panel.

Chiudere le faccende in sospeso

Uno dei pezzi più importanti qui è capire che in passato ci siamo di solito concentrati sulla creazione della parte visuale dell'interfaccia. Ora, prendiamo quello che abbiamo sempre fatto con CSS e lo rendiamo programmaticamente disponibile alle tecnologie assistive, fornendo un insieme esteso di stati, ruoli e proprietà che non semplicemente non sono disponibili in HTML.

Così, adesso, quando state lavorando ad un'interfaccia e vi vedete cambiare i nomi delle classi, cos'altro farete? Sì, corretto. Sono felice che abbiate risposto che cercherete di aggiungere un po' di ARIA all'interfaccia.

Semplice, vero?

Non tanto.

Cerchiamo una dicotomia nel comportamento per fornire la migliore interfaccia possibile alle persone che possono usufruire di un completo supporto per ARIA così come per quelle che non possono. Impostiamo delle combinazioni di tasti e dei comportamenti del focus con JavaScript sia in scenari ARIA sia in scenari non-ARIA.

Stiamo cambiando il comportamento per farlo combaciare con quello che vogliamo che sia per una serie di tab. Ma questo avrà senso solo quando potranno comportarsi come tab e questo accadrà quando sapremo di avere il supporto necessario per ARIA.

  1. Con il supporto per ARIA, i link saranno annunciati come tab quando gli verrà assegnato role="tab". Senza il supporto per ARIA saranno annunciati come un link e l'utente si aspetterà un comportamento da link da essi.
  2. Con il supporto per ARIA, usiamo tabindex="-1" sui tab non attivi (che sono in realtà link). Funzioneranno bene con il supporto per ARIA perché saremo in grado di reagire programmaticamente a quei tasti che sono stati progettati per una interfaccia a tab. Ma senza il supporto per ARIA, aggiungento tabindex="-1" a quei link, questi non sono più disponibili all'utente usando solo la tastiera. In realtà, abbiamo tolto della funzionalità.

E cosa succede alle tecnologie assistive più vecchie che non supportano ARIA? Non danno alcun annuncio all'utente che si trova su una tab ma ci sarà del codice JavaScript che assumerà che l'utente abbia la funzionalità delle tab.

E c'è la presa, signore e signori!

Il problema è che vogliamo che le cose si comportino in maniera differente quando ARIA è supportata rispetto a quando non lo è. Perché? In un tabbed panel senza ARIA vogliamo solo che si comportino come link. In un tabbed panel con ARIA, vogliamo che si comportino come tab. Vogliamo un'esperienza invisibile per tutti, sia che abbiano ARIA sia che non l'abbiano.

Dove ci conduce tutto ciò?

So bene che questi non sono tutti i possibili esempi in cui possiamo usare ARIA: ho scelto degli esempi specifici per illustrare il punto. Non fraintendetemi, credo molto in ARIA. La insegno in tutti i miei workshop di Ajax avanzato e accessibilità o di ARIA/HTML5/CSS3. Mi assicuro di sottolineare a tutte le persone che seguono i miei workshop che hanno bisogno di guardare ARIA e di implementarla dove esiste già il supporto sufficiente.

Il problema che abbiamo adesso è che ARIA è una questione “tutto o niente”. E scrivere degli script che rispettino sia una metodologia che supporta ARIA sia una che non la supporta è incredibilmente difficile, perché non c'è un modo sicuro per sapere lo stato del supporto per ARIA di uno specifico user agent: dipende da qualcosa che non possiamo rilevare: la giusta combinazione di browser, tecnologia assistiva ed una completa implementazione di ARIA.

Improvvisamente, il nostro stack del progressive enhancement si è rotto. Non possiamo rilevare il supporto per ARIA nel browser e pertanto non possiamo prendere delle decisioni sagge su come fornire l'accesso da tastiera più appropriato a seconda che lo scenario si con ARIA o senza ARIA.

Ecco quello che credo sia assolutamente necessario per portare a termine questo lavoro al meglio delle nostre capacità professionali, così da poter usare ARIA adesso e continuare ad usare il concetto di progressive enhancement:

  1. Dobbiamo essere in grado di individuare il supporto per ARIA nel browser, proprio come rileviamo altre capacità.
  2. Dobbiamo essere in grado di individuare il supporto per ARIA nella tecnologia assistiva così da sapere se ARIA è supportata in quegli user agent.

Armati di queste due informazioni possiamo tutti creare un'interfaccia che si comporti nel modo giusto nella situazione giusta.

Ho parlato con altri riguardo a questo prima d'ora e ho sempre sentito qualcosa come “presto non dovremo più preoccuparci degli scenari non-ARIA perché sarà supportata nei browser e nelle tecnologie assistive.” Avremo ovunque supporto per ARIA. Ma in quanti anni? Gli sviluppatori stanno già implementando ARIA perché gli è stato detto che è supportata dalle tecnologie assistive e dai browser. Se la stanno usando adesso, devono essere in grado di usarla in maniera appropriata adesso.

Viviamo in un mondo in cui tutti gli user agent praticamente non suportano ARIA. Quanto tempo ha impiegato IE6 per diventare un browser che non supportiamo più? Oh, aspettate, mi state dicendo che dovete ancora supportare IE? Ecco, questo è esattamente il punto. Avremo a che fare con uno scenario non-ARIA ancora per molto tempo: per questo abbiamo bisogno dei tool giusti per fornire una grande esperienza d'uso a tutti.

Illustrazioni: Carlo Brigatti

Share/Save/Bookmark
 

Discutiamone

Ti sembra interessante? Scrivi tu il primo commento


Cenni sull'autore

Derek Featherstone

Derek FeatherstoneDerek Featherstone ha fondato Further Ahead con sede in Canada, dove si rende la user experiences accessibile attraverso l'istruzione, le consulenze ed il design. Derek è Group Lead de The Web Standards Project e ed è anche un appassionato triatleta. Seguitelo su Twitter @feather, o fategli una visita su boxofchocolates.ca e SimplyAccessible.com.