Criteri di successo WCAG · Level A
WCAG 4.1.1: Analisi sintattica (Deprecato in WCAG 2.2)
WCAG 4.1.1 Parsing richiede che i contenuti web siano privi di errori HTML/XML gravi, come ad esempio ID duplicati, che potrebbero indurre le tecnologie assistive a interpretare in modo errato la pagina o a non riuscire a elaborarla. Sebbene sia deprecato in WCAG 2.2, le regole sottostanti di axe-core restano attive e le violazioni indicano comunque un reale rischio per l’accessibilità.
Cosa Significa Questa Regola
WCAG 4.1.1 Parsing è stato originariamente progettato per garantire che gli user agent, inclusi browser e tecnologie assistive, potessero analizzare e interpretare correttamente i contenuti web. Il criterio richiedeva che le pagine create in linguaggi di markup come HTML o XML soddisfacessero quattro condizioni strutturali: gli elementi devono avere tag di apertura e chiusura completi; gli elementi devono essere annidati secondo le loro specifiche; gli elementi non devono contenere attributi duplicati; e qualsiasi ID utilizzato nel contenuto deve essere univoco.
In WCAG 2.2, il W3C ha formalmente deprecato questo criterio. La motivazione è che i browser moderni sono diventati altamente resilienti all’HTML malformato, correggendo automaticamente la maggior parte degli errori strutturali prima che raggiungano l’albero di accessibilità. Di conseguenza, molte delle preoccupazioni originali—come tag non chiusi o elementi annidati in modo scorretto—non causano più danni pratici alle tecnologie assistive negli ambienti contemporanei.
Tuttavia, la deprecazione non significa che le preoccupazioni del criterio siano scomparse del tutto. Il W3C osserva esplicitamente che gli attributi ID duplicati restano un problema di accessibilità significativo. Quando due o più elementi condividono lo stesso valore di id, i browser devono prendere una decisione arbitraria su quale elemento associare ai riferimenti ARIA, alle associazioni di etichette o ai link a frammenti. Questa ambiguità può portare i lettori di schermo ad annunciare contenuti errati, saltare controlli interattivi o non esporre affatto le etichette dei moduli. La condizione di superamento del criterio è quindi oggi meglio intesa come: nessun valore ID duplicato compare nel DOM. Una pagina non soddisfa questo criterio quando gli ID sono duplicati in modi che interrompono le associazioni programmatiche da cui dipendono le tecnologie assistive.
Le eccezioni ufficiali nella specifica WCAG sono minime. Il criterio si applica ai contenuti creati in linguaggi di markup; non si applica ai contenuti generati da ambienti di scripting in cui l’autore non ha controllo diretto sul formato di output. In pratica, tuttavia, gli sviluppatori sono responsabili del DOM finale renderizzato indipendentemente dallo stack tecnologico utilizzato per produrlo.
Perché È Importante
Gli ID duplicati possono sembrare un problema minore di “pulizia del codice”, ma le loro conseguenze per gli utenti di tecnologie assistive possono essere gravi. I lettori di schermo come JAWS, NVDA e VoiceOver si basano sull’albero di accessibilità del browser, che a sua volta dipende da riferimenti ID risolti correttamente per costruire le relazioni tra gli elementi dell’interfaccia. Quando un ID è duplicato, il browser in genere risolve i riferimenti solo al primo elemento corrispondente nell’ordine del documento, ignorando silenziosamente gli elementi successivi con lo stesso ID.
Per utenti ciechi e ipovedenti, questo può significare che un campo di un modulo viene annunciato senza la sua etichetta, o che un messaggio di errore associato a un input tramite aria-describedby non viene mai letto ad alta voce. Si consideri un modulo di checkout su un sito di e-commerce in cui i campi dell’indirizzo di spedizione e quelli dell’indirizzo di fatturazione usano entrambi ID come city, zip e state. Un utente di lettore di schermo che compila la sezione di fatturazione potrebbe sentire l’etichetta della sezione di spedizione, con conseguente confusione, errori e potenziale abbandono della transazione.
Per utenti con disabilità cognitive, le associazioni di etichette interrotte significano che il testo visibile che leggono sullo schermo non corrisponde a ciò che il loro lettore di schermo o software di controllo vocale annuncia, creando una disconnessione disorientante che aumenta il carico cognitivo.
Per utenti con disabilità motorie che si affidano a software di input vocale come Dragon NaturallySpeaking, gli ID duplicati possono far sì che i comandi vocali diretti a un controllo specifico attivino l’elemento sbagliato, perché il software può fare affidamento internamente sul targeting basato sugli ID.
Oltre all’impatto sulla disabilità, gli ID duplicati influiscono anche sulla SEO: i crawler dei motori di ricerca che si basano su identificatori di frammenti per indicizzare sezioni specifiche della pagina possono indicizzare contenuti errati quando gli ID non sono univoci. Anche l’usabilità è degradata per tutti gli utenti quando i link di ancoraggio interni alla pagina portano alla posizione sbagliata nella pagina.
Circa 2,2 miliardi di persone nel mondo hanno qualche forma di disabilità visiva secondo l’Organizzazione Mondiale della Sanità. Una parte significativa di questi utenti si affida a lettori di schermo che sono direttamente influenzati da associazioni di ID interrotte. Garantire l’unicità degli ID è una delle correzioni a più basso sforzo e più alto impatto che un team di sviluppo possa implementare.
Regole Axe-core Correlate
Tre regole axe-core corrispondono direttamente alle problematiche sollevate da WCAG 4.1.1. Ognuna prende di mira una specifica manifestazione del problema degli ID duplicati:
- duplicate-id: Questa regola controlla l’intero DOM alla ricerca di qualsiasi valore di attributo
idche compaia su più di un elemento. Segnala tutti gli elementi oltre il primo che condividono un ID, indipendentemente dal fatto che tali elementi siano interattivi o referenziati da ARIA. È la più ampia delle tre regole e intercetta violazioni strutturali anche quando non è coinvolta alcuna relazione ARIA esplicita. Un trigger comune sono i framework basati su componenti che renderizzano lo stesso componente riutilizzabile più volte su una pagina senza generare ID univoci per ogni istanza. - duplicate-id-active: Questa regola restringe il suo focus agli ID duplicati su elementi interattivi o focalizzabili—pulsanti, link, input e qualsiasi elemento con un
tabindexnon negativo. L’impatto sull’accessibilità è maggiore qui perché sia le tecnologie assistive sia la navigazione da tastiera dipendono dalla capacità di identificare in modo univoco un controllo attivo. Quando un pulsante di invio e un’icona non correlata condividono lo stesso ID, sia gli annunci dell’ordine di tabulazione sia la gestione programmatica del focus possono rompersi. - duplicate-id-aria: Questa è la più critica delle tre regole. Segnala ID duplicati specificamente quando tali ID sono referenziati da attributi ARIA—
aria-labelledby,aria-describedby,aria-controls,aria-ownse attributi di relazione simili. Poiché questi attributi sono il meccanismo principale attraverso cui le tecnologie assistive comprendono le relazioni tra gli elementi, i duplicati in questo contesto interrompono direttamente il calcolo del nome accessibile e le relazioni di ruolo. Un esempio di fallimento sarebbe due elementi<div>conid='dialog-title'quando una modale usaaria-labelledby='dialog-title': il lettore di schermo annuncerà l’elemento che appare per primo nel DOM, che potrebbe non essere l’intestazione della finestra di dialogo prevista.
Gli strumenti automatizzati sono particolarmente adatti a individuare ID duplicati perché il controllo è puramente sintattico: lo strumento legge il DOM e confronta i valori degli ID. Non è strettamente richiesto alcun test manuale per questo criterio. Tuttavia, se gli ID sono generati dinamicamente dopo l’interazione dell’utente—ad esempio, uno scroll infinito che inietta nuovo contenuto con ID ripetuti—le scansioni automatizzate eseguite al caricamento della pagina possono non rilevare violazioni che compaiono solo in un secondo momento. In tali casi, i tester dovrebbero attivare il comportamento dinamico prima di eseguire le scansioni o monitorare il DOM utilizzando gli strumenti di sviluppo del browser dopo le interazioni.
Come Testare
- Scansione automatizzata con axe DevTools: Apri la pagina in Chrome o Firefox. Apri DevTools (F12), vai al pannello axe DevTools (o installa l’estensione del browser) ed esegui una scansione dell’intera pagina. Filtra i risultati per le regole duplicate-id, duplicate-id-active e duplicate-id-aria. Ogni violazione elencherà gli elementi interessati e i loro valori ID duplicati. Esporta il report se necessario per la documentazione di audit. Per Lighthouse, esegui un audit di accessibilità Lighthouse dalla scheda Lighthouse di DevTools e cerca l’audit “Document has multiple elements with the same id”.
- Verifica tramite console degli strumenti di sviluppo del browser: Apri la console del browser ed esegui il seguente snippet JavaScript per trovare tutti gli ID duplicati nella pagina corrente:
const ids = [...document.querySelectorAll('[id]')].map(el => el.id); const dupes = ids.filter((id, i) => ids.indexOf(id) !== i); console.log([...new Set(dupes)]);Questo stamperà un array di tutti i valori ID che compaiono più di una volta. Un array vuoto significa che non sono presenti duplicati. - Test con lettore di schermo usando NVDA e Firefox: Carica la pagina con NVDA in esecuzione. Naviga a un modulo che contiene campi con etichette associate tramite
for/idoaria-labelledby. Spostati con il tasto Tab su ciascun campo e ascolta attentamente se NVDA annuncia l’etichetta corretta. Se un campo viene annunciato senza etichetta o con l’etichetta sbagliata da una sezione diversa, la causa potrebbe essere un ID duplicato. Ripeti questo processo per eventuali regioni di riferimento ARIA, finestre di dialogo modali o widget che utilizzanoaria-controlsoaria-describedby. - VoiceOver e Safari su macOS: Abilita VoiceOver (Command+F5). Usa il rotor di VoiceOver (Control+Option+U) per aprire l’elenco dei controlli dei moduli o dei link e verifica che ogni controllo abbia un’etichetta univoca e annunciata correttamente. Entra in eventuali finestre di dialogo modali e conferma che il titolo della finestra di dialogo venga annunciato correttamente quando la finestra si apre.
- JAWS e Chrome: Con JAWS in esecuzione, apri la pagina e usa l’elenco dei campi modulo di JAWS (Insert+F5) per rivedere tutti gli elementi del modulo e le loro etichette associate. Verifica che nessun due campi condividano lo stesso testo di etichetta quando dovrebbero essere distinti.
- Test dei contenuti dinamici: Se la pagina utilizza scroll infinito, navigazione a pagina singola o finestre di dialogo modali iniettate tramite JavaScript, interagisci con queste funzionalità per caricare nuovo contenuto nel DOM, quindi esegui nuovamente la scansione automatizzata o lo snippet della console per verificare la presenza di duplicati introdotti dal contenuto dinamico.
Come Correggere
ID dei campi modulo duplicati tra sezioni ripetute — Errato
<!-- Shipping Address -->
<label for='city'>City</label>
<input type='text' id='city' name='shipping-city'>
<!-- Billing Address -->
<label for='city'>City</label>
<input type='text' id='city' name='billing-city'>
<!-- FAIL: Both inputs share id='city'. The second label's 'for' attribute
resolves to the first input, so screen readers announce the wrong field. -->
ID dei campi modulo duplicati tra sezioni ripetute — Corretto
<!-- Shipping Address -->
<label for='shipping-city'>City</label>
<input type='text' id='shipping-city' name='shipping-city'>
<!-- Billing Address -->
<label for='billing-city'>City</label>
<input type='text' id='billing-city' name='billing-city'>
<!-- PASS: Each input has a unique ID scoped to its section.
Screen readers correctly announce each field's label. -->
Componente riutilizzabile renderizzato più volte — Errato
<!-- Product Card 1 -->
<div class='product-card'>
<img id='product-img' src='shoe.jpg' alt='Running Shoe'>
<button id='add-to-cart' aria-describedby='product-desc'>Add to Cart</button>
<p id='product-desc'>Free shipping on orders over 500 TL.</p>
</div>
<!-- Product Card 2 (same template, duplicate IDs) -->
<div class='product-card'>
<img id='product-img' src='boot.jpg' alt='Hiking Boot'>
<button id='add-to-cart' aria-describedby='product-desc'>Add to Cart</button>
<p id='product-desc'>Free shipping on orders over 500 TL.</p>
</div>
<!-- FAIL: IDs duplicated across cards. aria-describedby on the second button
resolves to the <p> in the first card, not the second. -->
Componente riutilizzabile renderizzato più volte — Corretto
<!-- Product Card 1 -->
<div class='product-card'>
<img id='product-img-1' src='shoe.jpg' alt='Running Shoe'>
<button id='add-to-cart-1' aria-describedby='product-desc-1'>Add to Cart</button>
<p id='product-desc-1'>Free shipping on orders over 500 TL.</p>
</div>
<!-- Product Card 2 -->
<div class='product-card'>
<img id='product-img-2' src='boot.jpg' alt='Hiking Boot'>
<button id='add-to-cart-2' aria-describedby='product-desc-2'>Add to Cart</button>
<p id='product-desc-2'>Free shipping on orders over 500 TL.</p>
</div>
<!-- PASS: Each card's IDs are unique. ARIA references resolve correctly
within their own card. Use a counter, UUID, or slug-based strategy
to generate IDs in your component framework. -->
Finestra di dialogo modale con riferimento ARIA duplicato all’etichetta — Errato
<!-- A generic heading used as a reusable ID -->
<h1 id='dialog-title'>Welcome</h1>
<div role='dialog' aria-modal='true' aria-labelledby='dialog-title'>
<h2 id='dialog-title'>Confirm Your Order</h2>
<p>Are you sure you want to place this order?</p>
<button>Confirm</button>
<button>Cancel</button>
</div>
<!-- FAIL: Two elements share id='dialog-title'. The dialog's
aria-labelledby resolves to the page <h1>, not the dialog heading.
Screen readers will announce 'Welcome' as the dialog name. -->
Finestra di dialogo modale con riferimento ARIA duplicato all’etichetta — Corretto
<h1>Welcome</h1>
<div role='dialog' aria-modal='true' aria-labelledby='confirm-dialog-title'>
<h2 id='confirm-dialog-title'>Confirm Your Order</h2>
<p>Are you sure you want to place this order?</p>
<button>Confirm</button>
<button>Cancel</button>
</div>
<!-- PASS: The dialog heading has a unique, descriptive ID.
aria-labelledby correctly identifies the dialog to screen readers
as 'Confirm Your Order'. -->
Errori Comuni
- Copiare e incollare il markup dei componenti senza aggiornare gli ID: Gli sviluppatori spesso duplicano una sezione HTML funzionante per una seconda istanza (un secondo blocco di indirizzo, un secondo pannello di tab, un secondo elemento di accordion) e dimenticano di aggiornare tutti i valori ID affinché siano univoci. Stabilisci una convenzione di denominazione come
component-name-index(ad esempio,accordion-panel-1,accordion-panel-2) e applicala in fase di code review. - Utilizzare ID statici nei componenti del framework senza una strategia di chiavi univoche: React, Vue, Angular e framework simili possono renderizzare lo stesso componente decine di volte su una pagina. Usare un
id='search-input'hardcoded all’interno di un componente riutilizzabile creerà tanti duplicati quanti sono le istanze. Deriva sempre gli ID dalle props, da un contatore o da un’utility comeuseId()in React 18+. - Affidarsi al targeting tramite classi CSS invece di correggere l’HTML: Alcuni sviluppatori aggirano i problemi di ID duplicati passando i selettori JavaScript da
getElementByIdaquerySelectorcon una classe, lasciando però gli ID duplicati in posizione. Questo può risolvere il comportamento visivo ma non fa nulla per correggere le associazioni dell’albero di accessibilità interrotte. - Loop di templating lato server che generano lo stesso ID a ogni iterazione: Un template Jinja2, Blade o Twig che renderizza
id='item-title'all’interno di un loop{% for item in items %}produrrà un duplicato per ogni elemento nella lista. Aggiungi sempre l’indice del loop o l’identificatore dell’elemento all’ID:id='item-title-{{ loop.index }}'. - Ignorare gli ID in elementi nascosti o fuori dallo schermo: Gli elementi con
display: noneovisibility: hiddensono ancora presenti nel DOM e i loro ID sono ancora registrati. Un template di modale nascosta che condivide un ID con un elemento visibile causerà gli stessi errori di parsing. Usa l’attributohiddeno assicurati che i template nascosti utilizzino ID univoci. - Dare per scontato che lo scoping allo Shadow DOM risolva il problema: Gli ID all’interno dello Shadow DOM nativo sono limitati al loro ambito e non vanno in conflitto con gli ID nel light DOM o in altre radici shadow. Tuttavia, molte librerie di componenti utilizzano un polyfill o un approccio non standard che non fornisce un vero scoping. Verifica l’output DOM effettivo invece di presumere il comportamento del framework.
- Generare ID basati su contenuti forniti dall’utente senza sanitizzazione o deduplicazione: Creare ID da nomi di prodotti, titoli di articoli o altri testi dinamici può produrre collisioni quando due elementi condividono lo stesso nome (ad esempio, due prodotti entrambi chiamati “Classic” che generano entrambi
id='classic'). Aggiungi sempre una chiave di database univoca o un indice agli ID derivati dai contenuti. - Non testare dopo la navigazione lato client nelle single-page application: Le SPA che iniettano nuovo contenuto di route nel DOM senza un ricaricamento completo della pagina possono accumulare ID dalle route visitate in precedenza se il vecchio contenuto non viene correttamente smontato. Esegui le scansioni axe dopo aver navigato tra le route, non solo al caricamento iniziale.
- Dimenticare gli ID utilizzati negli elementi SVG
<defs>e<use>: I pattern di sprite SVG che definiscono simboli con ID all’interno di<defs>e poi li referenziano con<use href='#icon-arrow'>possono creare ID duplicati se la stessa definizione di simbolo è inclusa più volte su una pagina. Centralizza le definizioni degli sprite SVG e includile una sola volta. - Trascurare gli ID generati da widget di terze parti, plugin di chat o script di analytics: Gli script di terze parti a volte iniettano elementi con ID hardcoded. Se il tuo codice utilizza lo stesso ID, si verifica un conflitto che potresti non notare durante lo sviluppo. Analizza l’intero DOM renderizzato, incluso il contenuto di terze parti, e segnala i conflitti ai fornitori o applica uno spazio dei nomi ai tuoi ID per evitare collisioni.
Relazione con le Normative di Accessibilità della Turchia
La Circolare Presidenziale 2025/10 della Turchia, pubblicata nella Gazzetta Ufficiale n. 32933 il 21 giugno 2025, stabilisce requisiti obbligatori di accessibilità web per un’ampia serie di enti pubblici e privati che operano in Turchia. La circolare adotta WCAG 2.2 come standard tecnico di riferimento, rendendo la conformità al Livello A la soglia legale minima per tutti gli enti interessati.
WCAG 4.1.1 Parsing è un criterio di Livello A. Anche se il W3C lo ha deprecato in WCAG 2.2, le regole axe-core che applicano la sua preoccupazione principale—gli ID univoci—restano attive e continuano a essere segnalate negli audit di accessibilità condotti rispetto a WCAG 2.2. Gli audit regolatori turchi e le verifiche di conformità che utilizzano strumenti di scansione automatizzati segnaleranno quindi le violazioni duplicate-id come potenziali fallimenti di Livello A, indipendentemente dallo stato deprecato del criterio a livello di specifica. Le organizzazioni che intendono dimostrare la conformità dovrebbero trattare le violazioni di ID duplicati come problemi bloccanti.
Gli enti coperti dalla Circolare Presidenziale 2025/10 includono un’ampia gamma di istituzioni pubbliche e organizzazioni del settore privato: tutti gli organi di governo centrali e locali e le loro agenzie affiliate; banche e istituzioni finanziarie regolamentate dalla legge bancaria turca; ospedali e fornitori di assistenza sanitaria privati; operatori di telecomunicazioni che servono 200.000 o più abbonati; piattaforme di e-commerce e marketplace online; agenzie di viaggio e tour operator; aziende di trasporto private che operano in regime di concessione pubblica; e scuole e istituti di istruzione privati autorizzati dal Ministero dell’Istruzione Nazionale (MoNE).
La circolare stabilisce una tempistica di conformità graduale. Le istituzioni pubbliche devono raggiungere la piena conformità al Livello A entro un anno dalla data di pubblicazione della circolare. Le entità del settore privato nelle categorie coperte hanno due anni per raggiungere lo stesso standard. Il mancato rispetto espone gli enti interessati a controlli regolatori, potenziali sanzioni amministrative e rischi reputazionali in un mercato sempre più attento all’accessibilità.
Per le organizzazioni turche, affrontare le violazioni di ID duplicati è particolarmente rilevante nei contesti in cui sono coinvolti moduli digitali, flussi di pagamento online, portali di servizi governativi e sistemi di prenotazione sanitaria. Questi sono esattamente i tipi di interfacce che più probabilmente utilizzano sezioni di moduli ripetute, componenti riutilizzabili e integrazioni di widget di terze parti che introducono ID duplicati. Stabilire test di accessibilità automatizzati—ad esempio integrando axe-core nelle pipeline CI/CD—come parte del processo di sviluppo è sia una best practice tecnica sia una strategia pragmatica per mantenere una conformità normativa continua ai requisiti della circolare.
