Il contrasto che i tool di accessibilità non vedono: ho fatto un'estensione Chrome per gli stati
Ti è mai capitato di passare tutti i controlli automatici di accessibilità — usando axe, Lighthouse, WAVE — vederli verdi dappertutto, e poi accorgerti guardando la pagina che l’anello di focus è quasi invisibile, o che il testo di un link sbiadisce quando ci passi sopra col mouse?
Non è colpa tua e non è colpa degli strumenti: è che stanno guardando la pagina nel momento sbagliato. E siccome quella cosa mi dava fastidio da un po’, mi sono deciso e ho scritto un’estensione Chrome per stanarla: si chiama A11y State Contrast Checker.
Il punto cieco: gli strumenti guardano solo lo stato “a riposo”
axe-core, Lighthouse e WAVE ispezionano il DOM così com’è nel momento della scansione: lo stato a riposo della pagina. È lì che misurano il contrasto del testo, dei bordi, delle icone.
Il problema è che i problemi di contrasto possono non esistere, a riposo, compaiono solo quando un elemento è nello stato :hover, :focus o :focus-visible:
- un colore di testo che all’hover diventa un grigio troppo tenue;
- un anello di focus dal contrasto insufficiente contro lo sfondo (l’ho raccontato per esteso in Basta
:focus { outline: none; }); - un’icona che si “lava via” quando ci passi sopra.
Nessuno di questi stati è attivo mentre lo strumento automatico fa la sua scansione. Risultato: quelle violazioni passano inosservate e finiscono in produzione col bollino verde. È un cugino stretto del problema di cui parlavo a proposito di APCA e del contrasto calcolato male: il contrasto è misurabile, ma solo se lo misuri nel contesto giusto.
Perché è nata l’estensione
Certo, puoi controllare gli stati a mano. Apri i DevTools, forzi :hover su un elemento dal pannello degli stili, leggi il colore del testo, leggi quello dello sfondo, li dai in pasto a un calcolatore di contrasto, segni se passa. Poi ripeti per :focus. Poi passi all’elemento dopo. E a quello dopo ancora.
È un lavoro tedioso, lento e facilissimo da dimenticare — proprio perché è tedioso. Ed è esattamente da questa frustrazione che è nata l’idea: se un controllo è così noioso da fare a mano, prima o poi smetti di farlo. Meglio darlo in pasto a una macchina.
Cosa fa A11y State Contrast Checker
L’estensione fa una cosa sola: controlla il contrasto WCAG negli stati interattivi. La apri su una pagina qualsiasi, premi Run audit, e ti dice dove hover e focus rompono il contrasto.
Sotto il cofano non reimplementa la cascata CSS (una via lastricata di errori): forza i veri pseudo-stati usando il motore di rendering di Chrome e poi legge gli stili calcolati. Così specificità, !important, custom properties e media query sono risolte correttamente dal browser stesso — non da una mia approssimazione.
I controlli sono tre:
- 1.4.3 Contrasto minimo — testo contro sfondo su
:hovere:focus(4.5:1, oppure 3:1 per il testo grande). - 1.4.11 Contrasto non testuale — l’anello di focus contro ciò che lo circonda (3:1).
- 1.4.11 sulle icone — per i controlli con la sola icona, il
fill/strokedell’SVG contro lo sfondo (3:1).
Il senso è tutto in quel micro-esempio che passa a riposo e fallisce nello stato:
.link {
color: #1f7a5c; /* a riposo: ottimo contrasto sul bianco, passa */
}
.link:hover {
color: #9cc7b8; /* all'hover: sbiadisce, ~1.8:1, fallisce — ma nessuno strumento se ne accorge */
}
Il calzolaio con le scarpe bucate
Sai qual è stata la prima pagina su cui ho lanciato l’estensione? Questo blog.
E ovviamente — legge di Murphy dell’accessibilità — ho trovato dei fail proprio sugli stati interattivi. Il classico calzolaio con le scarpe bucate: scrivo di contrasto e di focus, e intanto il mio stesso sito aveva degli stati che non passavano. Umiliante e istruttivo insieme.
La buona notizia è che li ho sistemati: i fix al design sono online da oggi, insieme a questo post. Se lo strumento è servito prima di tutto a me, forse serve anche a te.
Come si usa, in 3 passi
- Apri la pagina che vuoi controllare.
- Clicca l’icona dell’estensione e premi Run audit.
- Leggi la tabella dei risultati: elemento, stato, controllo WCAG, rapporto misurato, rapporto richiesto, esito. Clicca una riga per far scorrere la pagina fino all’elemento e evidenziarlo, così lo verifichi con l’occhio.
Un dettaglio che spiazza al primo utilizzo: mentre l’audit gira, Chrome mostra la sua barra gialla ”… ha avviato il debug di questo browser”. È previsto e non è un problema: è proprio così che l’estensione forza gli stati interattivi. Sparisce appena la scansione finisce.
Sii consapevole dei limiti
Non è una bacchetta magica, e preferisco dirtelo io. Al momento:
- risolve lo sfondo guardando solo i livelli
background-color(non immagini né gradienti); - non analizza gli iframe cross-origin;
- sulle pagine molto grandi si ferma a un tetto di elementi e restituisce risultati parziali.
Resta uno strumento che copre un buco preciso, non un sostituto di axe o Lighthouse: quelli continuano a fare il loro lavoro sullo stato a riposo, questo aggiunge il pezzo mancante sugli stati.
Da non dimenticare, sugli stati interattivi
- Il colore del testo cambia su
:hover? Se sì, hai verificato che il nuovo colore passi 4.5:1? - L’anello di focus (
outline, o ilbox-shadowusato come anello) ha almeno 3:1 contro lo sfondo su cui compare? - I controlli con la sola icona mantengono 3:1 anche all’hover, quando spesso il colore cambia?
- Stai controllando
:focuse:focus-visible, che possono avere stili diversi? - Hai fatto questo controllo su sfondi diversi (header scuro, card chiara, footer…), non solo sul bianco della pagina?
Provala (e dimmi com’è andata)
A11y State Contrast Checker è open source (licenza MIT), non raccoglie alcun dato e non fa nessuna richiesta di rete: gira tutto in locale. La trovi su GitHub, con le istruzioni di installazione nel README:
👉 github.com/conlaccento/a11y-state-contrast-checker
In questo momento è anche in fase di verifica sul Chrome Web Store: appena approvata potrai installarla con un clic, senza passare dal caricamento manuale. Nel frattempo la strada da GitHub funziona benissimo.
Se la provi e trovi fail interessanti sui tuoi progetti — o se becchi un bug nell’estensione — scrivimi: il feedback è la cosa che la fa migliorare più in fretta.
Peace&Love! ✌️