Quando i CSS non bastano: requisiti JavaScript per componenti accessibili

Pubblicato: 2022-03-10
Riepilogo rapido ↬ Avviso spoiler: suggerimenti, modali, schede, caroselli e menu a discesa sono alcuni dei componenti dell'interfaccia utente che richiedono più del CSS. Per garantire l'accessibilità della tua interfaccia, JavaScript è un'aggiunta necessaria per eseguire la gestione del focus, rispondere agli eventi della tastiera e attivare gli attributi ARIA.

Come autore di ModernCSS.dev, sono un grande sostenitore delle soluzioni CSS. E adoro vedere i modi intelligenti in cui le persone usano i CSS per progetti e interattività davvero pronti all'uso! Tuttavia, ho notato una tendenza verso la promozione di componenti "solo CSS" utilizzando metodi come "hackbox". Sfortunatamente, hack come questi lasciano una quantità significativa di utenti incapaci di utilizzare la tua interfaccia.

Questo articolo copre diversi componenti comuni e perché CSS non è sufficiente per coprire l'accessibilità descrivendo in dettaglio i requisiti JavaScript. Questi requisiti si basano sulle Linee guida per l'accessibilità dei contenuti Web (WCAG) e su ricerche aggiuntive da parte di esperti di accessibilità. Non prescriverò soluzioni JavaScript o CSS dimostrativi, ma esaminerò piuttosto ciò di cui è necessario tenere conto durante la creazione di ciascun componente. Un framework JavaScript può certamente essere utilizzato ma non è necessario per aggiungere gli eventi e le funzionalità discusse.

I requisiti elencati sono generalmente non opzionali: sono necessari per garantire l'accessibilità dei componenti.

Se stai usando un framework o una libreria di componenti, puoi usare questo articolo per valutare se i componenti forniti soddisfano i requisiti di accessibilità . È importante sapere che molti degli elementi annotati non saranno completamente coperti da strumenti di test di accessibilità automatizzati come aXe e quindi necessitano di alcuni test manuali. Oppure puoi utilizzare un framework di test come Cypress per creare test per la funzionalità richiesta.

Tieni presente che questo articolo è incentrato sull'informazione delle considerazioni su JavaScript per ciascun componente dell'interfaccia. Questa non è una risorsa completa per tutti i dettagli di implementazione per la creazione di componenti completamente accessibili, come aria necessaria o anche markup. Le risorse sono incluse per ogni tipo per aiutarti a saperne di più sulle considerazioni più ampie per ciascun componente.

Altro dopo il salto! Continua a leggere sotto ↓

Determinare se solo CSS è una soluzione appropriata

Ecco alcune domande da porre prima di procedere con una soluzione solo CSS. Tratteremo alcuni dei termini presentati qui in un contesto più ampio insieme ai relativi componenti.

  • È questo per il tuo divertimento?
    Quindi punta assolutamente sui CSS, supera i limiti e impara cosa può fare la lingua!
  • La funzione include la visualizzazione e l'occultamento dei contenuti?
    Quindi hai bisogno di JS per alternare almeno aria e abilitare la chiusura su Esc . Per alcuni tipi di componenti che cambiano anche lo stato, potrebbe anche essere necessario comunicare le modifiche attivando gli aggiornamenti all'interno di una regione attiva ARIA.
  • L'ordine di messa a fuoco naturale è il più ideale?
    Se l'ordine naturale perde la relazione tra un trigger e l'elemento che ha attivato, o un utente della tastiera non può nemmeno accedere al contenuto tramite l'ordine di tabulazione naturale, è necessario che JS assista nella gestione del focus.
  • Il controllo stilizzato offre le informazioni corrette sulla funzionalità?
    Gli utenti di tecnologie assistive come i lettori di schermo ricevono informazioni basate sulla semantica e su ARIA che li aiuta a determinare cosa fa un controllo. Inoltre, gli utenti del riconoscimento vocale devono essere in grado di identificare l'etichetta o il tipo del componente per elaborare la frase da utilizzare per azionare i controlli. Ad esempio, se il tuo componente ha uno stile simile alle schede ma utilizza i pulsanti di opzione per "funzionare" come le schede, un lettore dello schermo potrebbe sentire "pulsante di opzione" e un utente vocale potrebbe provare a utilizzare la parola "scheda" per azionarli. In questi casi, avrai bisogno di JS per abilitare l'uso dei controlli e della semantica appropriati per ottenere la funzionalità desiderata.
  • L'effetto si basa sul passaggio del mouse e/o sulla messa a fuoco?
    Quindi potresti aver bisogno di JS per fornire assistenza in una soluzione alternativa per fornire parità di accesso o accesso persistente al contenuto, in particolare per gli utenti touch screen e quelli che utilizzano uno zoom del desktop superiore al 200% o un software di ingrandimento.

Suggerimento rapido : un altro riferimento durante la creazione di qualsiasi tipo di controllo personalizzato è l'elenco di controllo per lo sviluppo accessibile del controllo personalizzato dalla guida W3 "Using ARIA". Questo menziona diversi punti sopra, con alcune considerazioni di progettazione e semantica aggiuntive.

Suggerimenti

Restringere la definizione di una descrizione comando è un po' complicato, ma per questa sezione stiamo parlando di piccole etichette di testo che appaiono al passaggio del mouse vicino a un elemento di attivazione. Si sovrappongono ad altri contenuti, non richiedono interazione e scompaiono quando un utente rimuove il passaggio del mouse o lo stato attivo.

Esempi di suggerimenti da GitHub, Whimsical e Notion
Esempi di suggerimenti da GitHub, Whimsical e Notion. (Grande anteprima)

La soluzione solo CSS qui può sembrare completamente soddisfacente e può essere realizzata con qualcosa del tipo:

 <button class="tooltip-trigger">I have a tooltip</button> <span class="tooltip">Tooltip</span> .tooltip { display: none; } .tooltip-trigger:hover + .tooltip, .tooltip-trigger:focus + .tooltip { display: block; }

Tuttavia, questo ignora un bel elenco di problemi di accessibilità ed esclude molti utenti dall'accesso al contenuto del suggerimento.

Un ampio gruppo di utenti esclusi sono quelli che utilizzano i touch screen in cui :hover potrebbe non essere attivato poiché sui touch screen, un evento :hover si attiva in sincronia con un evento :focus . Ciò significa che qualsiasi azione correlata collegata all'elemento di attivazione, come un pulsante o un collegamento, si attiverà insieme alla descrizione comando che viene rivelata. Ciò significa che l'utente potrebbe perdere il suggerimento o non avere il tempo di leggerne il contenuto.

Nel caso in cui la descrizione comando sia collegata a un elemento interattivo senza eventi, la descrizione comando può essere visualizzata ma non essere ignorata fino a quando un altro elemento non viene focalizzato e, nel frattempo, può bloccare il contenuto e impedire a un utente di svolgere un'attività.

Inoltre, gli utenti che hanno bisogno di utilizzare il software di zoom o ingrandimento per navigare incontrano anche una certa barriera all'utilizzo dei suggerimenti. Poiché i suggerimenti vengono visualizzati al passaggio del mouse, se questi utenti devono modificare il proprio campo visivo eseguendo una panoramica dello schermo per leggere il suggerimento, è possibile che scompaia. Le descrizioni comandi rimuovono anche il controllo dall'utente poiché spesso non c'è nulla da dire all'utente che una descrizione comandi apparirà in anticipo. La sovrapposizione del contenuto potrebbe impedire loro di svolgere un'attività. In alcune circostanze, come una descrizione comando legata a un campo modulo, le tastiere mobili o altre tastiere su schermo possono oscurare il contenuto della descrizione comando. E, se non sono adeguatamente collegati all'elemento di attivazione, alcuni utenti di tecnologie assistive potrebbero non sapere nemmeno che è apparso un suggerimento.

La guida per il comportamento dei suggerimenti viene dal Criterio di successo WCAG 1.4.13 — Contenuto al passaggio del mouse o Focus. Questo criterio ha lo scopo di aiutare gli utenti ipovedenti e coloro che utilizzano software di zoom e ingrandimento. I principi guida per i suggerimenti (e altri contenuti che appaiono al passaggio del mouse e allo stato attivo) includono:

  • Inammissibile
    Il suggerimento può essere eliminato senza spostare il passaggio del mouse o il focus
  • Aleggiabile
    Il contenuto della descrizione comando rivelato può essere spostato con il mouse senza che scompaia
  • Persistente
    Il contenuto aggiuntivo non scompare in base a un timeout, ma attende che un utente rimuova il passaggio del mouse o lo metta a fuoco o lo ignori in altro modo

Per soddisfare pienamente queste linee guida è necessaria l'assistenza JavaScript, in particolare per consentire l'eliminazione del contenuto.

  • Gli utenti della tecnologia assistiva presumeranno che il comportamento di eliminazione sia legato alla chiave Esc , che richiede un listener JavaScript.
  • Secondo la ricerca di Sarah Higley descritta nella sezione successiva, l'aggiunta di un pulsante "chiudi" visibile all'interno del suggerimento richiederebbe anche JavaScript per gestire il suo evento di chiusura.
  • È possibile che JavaScript possa aver bisogno di aumentare la tua soluzione di stile per garantire che un utente possa passare il mouse sopra il contenuto della descrizione comando senza che venga ignorato quando l'utente sposta il mouse.

Alternative alle descrizioni comandi

I suggerimenti dovrebbero essere l'ultima risorsa. Sarah Higley, un'esperta di accessibilità che ha una passione particolare per dissuadere dall'uso dei suggerimenti, offre questo semplice test:

"Perché aggiungo questo testo all'interfaccia utente? Dove altro potrebbe andare?”

— Sarah Higley dalla presentazione "Tooltips: Investigation Into Four Parts"

Sulla base della ricerca con cui Sarah è stata coinvolta per il suo ruolo in Microsoft, una soluzione alternativa è un "toggletip" dedicato. In sostanza, ciò significa fornire un elemento aggiuntivo per consentire a un utente di attivare intenzionalmente la visualizzazione e l'occultamento di contenuti extra . A differenza dei suggerimenti, i suggerimenti possono conservare la semantica degli elementi all'interno del contenuto rivelato. Inoltre, restituiscono all'utente il controllo della loro attivazione/disattivazione e mantengono la rilevabilità e l'operabilità da parte di più utenti e in particolare degli utenti touch screen.

Se hai ricordato che l'attributo title esiste, sappi solo che soffre degli stessi problemi che abbiamo notato dalla nostra soluzione solo CSS. In altre parole, non utilizzare il title presumendo che sia una soluzione di descrizione comando accettabile.

Per ulteriori informazioni, dai un'occhiata alla presentazione di Sarah su YouTube e al suo ampio articolo sui suggerimenti. Per saperne di più sui suggerimenti rispetto ai suggerimenti e un po' più di informazioni sul perché non usare title , consulta l'articolo di Heydon Pickering da Componenti inclusi: suggerimenti e suggerimenti.

Modali

I modali, noti anche come lightbox o finestre di dialogo, sono finestre in-page che vengono visualizzate dopo un'azione di attivazione. Si sovrappongono ad altri contenuti della pagina, possono contenere informazioni strutturate incluse azioni aggiuntive e spesso hanno uno sfondo semitrasparente per aiutare a distinguere la finestra modale dal resto della pagina.

Esempi di modali da GitHub e Material Design
Esempi di modali da GitHub e Material Design. (Grande anteprima)

Ho visto alcune varianti di un modale solo CSS (e sono colpevole di averne creato uno per una versione precedente del mio portfolio). Possono usare il "hack della casella di controllo", utilizzare il comportamento di :target , o provare a modellarlo su :focus (che probabilmente è davvero un suggerimento troppo grande sotto mentite spoglie).

Per quanto riguarda l'elemento di dialog HTML, tieni presente che non è considerato completamente accessibile. Quindi, mentre incoraggio assolutamente le persone a utilizzare l'HTML nativo prima di soluzioni personalizzate, sfortunatamente questo infrange quell'idea. Puoi saperne di più sul motivo per cui la finestra di dialog HTML non è accessibile.

A differenza delle descrizioni comandi, le modali hanno lo scopo di consentire contenuto strutturato. Ciò significa potenzialmente un'intestazione, alcuni contenuti di paragrafo ed elementi interattivi come collegamenti, pulsanti o persino moduli. Affinché la maggior parte degli utenti possa accedere a tale contenuto, devono essere in grado di utilizzare gli eventi della tastiera , in particolare le schede. Per un contenuto modale più lungo, anche i tasti freccia dovrebbero mantenere la possibilità di scorrere. E come i suggerimenti, dovrebbero essere ignorati con il tasto Esc e non c'è modo di abilitarlo solo con CSS.

JavaScript è richiesto per la gestione del focus all'interno delle modali. I modali dovrebbero intercettare lo stato attivo, il che significa che una volta che lo stato attivo è all'interno del modale, un utente non dovrebbe essere in grado di estrarlo dal contenuto della pagina dietro di esso. Ma prima, l'attenzione deve entrare nel modale, che richiede anche JavaScript per una soluzione modale completamente accessibile.

Ecco la sequenza di eventi correlati modali che devono essere gestiti con JavaScript:

  1. Il listener di eventi su un pulsante apre il modale
  2. Il focus è posto all'interno del modale; quale elemento varia in base al contenuto modale (vedi albero decisionale)
  3. Il focus è intrappolato all'interno del modale fino a quando non viene respinto
  4. Preferibilmente, un utente è in grado di chiudere un modale con il tasto Esc oltre a un pulsante di chiusura dedicato o un'azione distruttiva del pulsante come "Annulla" se è richiesto il riconoscimento del contenuto modale
    1. Se Esc è consentito, anche i clic sullo sfondo modale dovrebbero eliminare il modale
  5. Al momento del licenziamento, se non si è verificata alcuna navigazione, lo stato attivo viene riportato sull'elemento del pulsante di attivazione

Albero decisionale del focus modale

Basato sull'esempio di dialogo modale WAI-ARIA Authoring Practices, ecco un albero decisionale semplificato su dove mettere l'attenzione una volta aperta una modale. Il contesto determinerà sempre la scelta qui e idealmente la messa a fuoco è gestita oltre il semplice "primo elemento focalizzabile". In effetti, a volte è necessario selezionare elementi non focalizzabili.

  • L'oggetto principale del modale è una forma.
    Metti a fuoco il primo campo del modulo.
  • Il contenuto modale ha una lunghezza significativa e spinge le azioni modali fuori dalla vista.
    Metti a fuoco un'intestazione, se presente, o il primo paragrafo.
  • Lo scopo del modale è procedurale (esempio: conferma dell'azione) con più azioni disponibili.
    Concentrati sull'azione "meno distruttiva" in base al contesto (esempio: "OK").
  • Lo scopo del modale è procedurale con un'azione.
    Concentrati sul primo elemento focalizzabile

Suggerimento rapido : nel caso in cui sia necessario mettere a fuoco un elemento non attivabile, come un'intestazione o un paragrafo, aggiungi tabindex="-1" che consente all'elemento di diventare programmaticamente attivabile con JS ma non lo aggiunge all'ordine di tabulazione DOM .

Fare riferimento alla demo modale WAI-ARIA per ulteriori informazioni su altri requisiti per la configurazione di ARIA e ulteriori dettagli su come selezionare l'elemento a cui aggiungere il focus. La demo include anche JavaScript per esemplificare come eseguire la gestione del focus.

Per una soluzione pronta all'uso, Kitty Giraudel ha creato una finestra di dialogo 11y che include i requisiti delle funzionalità di cui abbiamo discusso. Adrian Roselli ha anche studiato la gestione del focus delle finestre di dialogo modali e ha creato una demo e raccolto informazioni su come diverse combinazioni di browser e screen reader comunicheranno l'elemento focalizzato.

Schede

Le interfacce a schede implicano una serie di trigger che visualizzano i riquadri dei contenuti corrispondenti uno alla volta. Gli "hack" CSS che potresti trovare per questi implicano l'uso di pulsanti di opzione stilizzati, o :target , che consentono entrambi di rivelare solo un singolo pannello alla volta.

Schede di esempio da Shopify Polaris e IBM Carbon
Schede di esempio da Shopify Polaris e IBM Carbon. (Grande anteprima)

Ecco le funzionalità della scheda che richiedono JavaScript:

  1. Attivazione dell'attributo aria-selected su true per la scheda corrente e false per le schede non selezionate
  2. Creazione di un tabindex mobile per distinguere la selezione delle schede dallo stato attivo
  3. Sposta lo stato attivo tra le schede rispondendo agli eventi dei tasti freccia (e facoltativamente Home ed End )

Facoltativamente, puoi fare in modo che la selezione della scheda segua lo stato attivo, il che significa che quando una scheda è focalizzata, viene anche selezionata e mostra il pannello delle schede associato. La WAI-ARIA Authoring Practices offre questa guida per scegliere se la selezione debba seguire il focus.

Indipendentemente dal fatto che tu scelga o meno di fare in modo che la selezione segua lo stato attivo, utilizzerai anche JavaScript per ascoltare gli eventi dei tasti freccia per spostare lo stato attivo tra gli elementi della scheda. Questo è un modello alternativo per consentire la navigazione delle opzioni di tabulazione poiché l'uso di un tabindex mobile (descritto di seguito) altera l'ordine naturale di attivazione delle tabulazioni della tastiera.

Informazioni su tabindex

Il concetto di un tabindex mobile è che il valore del valore tabindex è controllato a livello di codice per gestire l'ordine di focus degli elementi. Per quanto riguarda le schede, ciò significa che solo la scheda selezionata fa parte dell'ordine di messa a fuoco impostando tabindex="0" e le schede non selezionate sono impostate su tabindex="-1" che le rimuove dall'ordine di messa a fuoco naturale della tastiera.

Il motivo è che quando viene selezionata una scheda, la scheda successiva porterà l'attenzione di un utente all'interno del pannello delle schede associato. Puoi scegliere di rendere attivabile l'elemento che è il pannello a schede assegnandolo tabindex="0" , o che potrebbe non essere necessario se c'è la garanzia di un elemento attivabile all'interno del pannello a schede . Se il contenuto del tuo pannello a schede sarà più variabile o complesso, potresti prendere in considerazione la gestione dell'attenzione in base all'albero decisionale che abbiamo esaminato per i modali.

Esempi di schemi di tabulazione

Di seguito sono riportati alcuni modelli di riferimento per la creazione di schede:

  • Demo del pannello a schede della Deque University
  • Test dei widget delle schede di Scott O'Hara (verifica diversi modelli funzionali)
  • Interfacce a schede dai componenti inclusi di Heydon Pickering, che dimostra come le schede possono essere un miglioramento progressivo di un sommario

Caroselli

Chiamati anche slideshow o slider, i caroselli coinvolgono una serie di pannelli di contenuto rotanti (detti anche "diapositive") che includono meccanismi di controllo. Li troverai in molte configurazioni con un'ampia gamma di contenuti. Sono in qualche modo notoriamente considerati un cattivo modello di progettazione.

Un esempio di demo del carosello creato con bxSlider
Un esempio di demo del carosello creato con bxSlider. (Grande anteprima)

La parte difficile dei caroselli solo CSS è che potrebbero non offrire controlli o potrebbero utilizzare controlli imprevisti per manipolare il movimento del carosello. Ad esempio, puoi utilizzare di nuovo la "hack box di controllo" per causare la transizione del carosello, ma le caselle di controllo trasmettono il tipo sbagliato di informazioni sull'interazione agli utenti della tecnologia assistiva. Inoltre, se si impostano le etichette delle caselle di controllo in modo che appaiano visivamente come frecce avanti e indietro, è probabile che gli utenti del software di riconoscimento vocale diano l'impressione sbagliata di ciò che dovrebbero dire per controllare il carosello.

Più di recente, è arrivato il supporto CSS nativo per lo snap a scorrimento. All'inizio, questa sembra la soluzione perfetta solo per CSS. Ma anche il controllo automatizzato dell'accessibilità li contrassegnerà come non navigabili dagli utenti della tastiera nel caso in cui non ci sia modo di navigarli tramite elementi interattivi. Ci sono altri problemi di accessibilità e di esperienza dell'utente con il comportamento predefinito di questa funzione, alcuni dei quali ho incluso nella mia demo dello snap a scorrimento su SmolCSS.

Nonostante l'ampia gamma di aspetto dei caroselli, ci sono alcuni tratti comuni. Un'opzione è creare un carosello usando il markup delle schede poiché in effetti è la stessa interfaccia sottostante con una presentazione visiva alterata. Rispetto alle schede, i caroselli possono offrire controlli aggiuntivi per il precedente e il successivo e anche mettere in pausa se il carosello è in riproduzione automatica.

Di seguito sono riportate considerazioni su JavaScript a seconda delle funzionalità del carosello:

  • Utilizzo dei controlli impaginati
    Dopo aver selezionato un elemento numerato, focalizzare a livello di codice la diapositiva del carosello associata. Ciò comporterà la configurazione di contenitori di diapositive utilizzando tabindex mobile in modo da poter mettere a fuoco la diapositiva corrente, ma impedire l'accesso alle diapositive fuori schermo.
  • Utilizzo della riproduzione automatica
    Includi un controllo di pausa e abilita anche la pausa quando la diapositiva è posizionata al passaggio del mouse o un elemento interattivo al suo interno è attivo. Inoltre, puoi verificare la presenza di prefers-reduced-motion all'interno di JavaScript per caricare la presentazione in uno stato in pausa per rispettare le preferenze dell'utente.
  • Utilizzo dei controlli precedente/successivo
    Includere un elemento visivamente nascosto contrassegnato come aria-live="polite" e dopo l'attivazione di questi controlli, popolare l'area live con un'indicazione della posizione corrente, ad esempio "Diapositiva 2 di 4".

Risorse per la costruzione di caroselli accessibili

  • Dettagli e considerazioni approfonditi sull'implementazione, nonché un esempio di codice completo dal tutorial sull'accessibilità del Web W3C sui caroselli
  • L'esempio della Deque University di migliorare un'interfaccia a schede in un carosello
  • L'esempio WAI-ARIA Authoring Practices di un carosello di immagini a rotazione automatica
  • Una selezione di risorse del carosello nella carrellata di componenti accessibili di Smashing

Menu a tendina

Si riferisce a un componente in cui un pulsante attiva o disattiva un elenco di collegamenti, generalmente utilizzati per i menu di navigazione. Le implementazioni CSS che si fermano a mostrare il menu su :hover o :focus perdono solo alcuni dettagli importanti.

Esempi di menu a discesa da Dribbble, Ricerca Google e GitHub
Esempi di menu a discesa da Dribbble, Ricerca Google e GitHub. (Grande anteprima)

Lo ammetto, ho persino pensato che usando la più recente proprietà :focus-within avremmo potuto implementare in sicurezza una soluzione solo CSS. Vedrai che il mio articolo sui menu a discesa CSS è stato modificato per includere note e risorse sul JavaScript necessario (ho mantenuto il titolo in modo che gli altri che cercano quella soluzione, si spera, completino anche l'implementazione JS). In particolare, fare affidamento solo sui CSS significa violare il criterio di successo WCAG 1.4.13: contenuto su Hover o Focus che abbiamo appreso con i suggerimenti.

Dobbiamo aggiungere JavaScript per alcune tecniche che dovrebbero suonare familiari a questo punto:

  • Commutazione aria-expanded sul pulsante del menu tra true e false ascoltando gli eventi di click
  • Chiusura di un menu aperto dopo l'uso del tasto Esc e ritorno dello stato attivo al pulsante di attivazione/disattivazione del menu
  • Preferibilmente, chiudendo i menu aperti quando lo stato attivo viene spostato al di fuori del menu
  • Opzionale : implementare i tasti freccia, nonché i tasti Home e End per la navigazione con la tastiera tra i pulsanti di attivazione/disattivazione del menu e i collegamenti all'interno dei menu a discesa

Consiglio rapido : Garantire la corretta implementazione del menu a tendina associando la visualizzazione del menu al selettore di .dropdown-toggle[aria-expanded= " true " ] + .dropdown piuttosto che basare la visualizzazione del menu sulla presenza di un JS- aggiuntivo classe aggiunta come active . Questo rimuove anche un po' di complessità dalla tua soluzione JS!

Questo è anche indicato come "schema di divulgazione" e puoi trovare maggiori dettagli nel menu di navigazione di divulgazione di esempio di WAI-ARIA Authoring Practices.

Risorse aggiuntive sulla creazione di componenti accessibili

  • La guida completa di Smashing ai componenti front-end accessibili
  • L'articolo di Carie Fisher Good, Better, Best: Untangling The Complex World Of Accessible Patterns
  • Demo e informazioni su modelli di progettazione comuni e widget disponibili da WAI-ARIA Authoring Practices 1.2
  • Biblioteca del codice della Deque University
  • Componenti accessibili di Scott O'Hara
  • Componenti inclusi di Heydon Pickering