WCAG framgångskriterier · Level A
WCAG 4.1.1: Parsning (föråldrad i WCAG 2.2)
WCAG 4.1.1 Parsing kräver att webbinnehåll är fritt från allvarliga HTML/XML-fel – såsom duplicerade ID:n – som kan få hjälpmedelstekniker att misstolka sidan eller misslyckas med att bearbeta den. Även om riktlinjen är utfasad i WCAG 2.2 är de underliggande axe-core-reglerna fortfarande aktiva och överträdelser innebär fortfarande en verklig tillgänglighetsrisk.
Vad den här regeln innebär
WCAG 4.1.1 Parsing utformades ursprungligen för att säkerställa att användaragenter, inklusive webbläsare och hjälpmedelsteknik, kunde tolka och tolka webbinnehåll korrekt. Kriteriet krävde att sidor som skrivs i märkspråk som HTML eller XML uppfyller fyra strukturella villkor: element måste ha kompletta start- och sluttaggar; element måste vara nästlade enligt sina specifikationer; element får inte innehålla duplicerade attribut; och alla ID:n som används i innehållet måste vara unika.
I WCAG 2.2 avvecklade W3C formellt detta kriterium. Motiveringen var att moderna webbläsare har blivit mycket motståndskraftiga mot felaktig HTML och korrigerar automatiskt de flesta strukturella fel innan de når tillgänglighetsträdet. Som en följd orsakar många av de ursprungliga problemen – såsom oavslutade taggar eller felaktigt nästlade element – inte längre praktisk skada för hjälpmedelsteknik i moderna miljöer.
Avveckling innebär dock inte att kriteriets problem helt har försvunnit. W3C påpekar uttryckligen att duplicerade ID-attribut fortfarande är ett betydande tillgänglighetsproblem. När två eller fler element delar samma id-värde måste webbläsare fatta ett godtyckligt beslut om vilket element som ska kopplas till ARIA-referenser, etikettassociationer eller fragmentlänkar. Denna tvetydighet kan göra att skärmläsare läser upp fel innehåll, hoppar över interaktiva kontroller eller inte exponerar fältetiketter alls. Kriteriets godkännandekrav förstås därför bäst idag som: inga duplicerade ID-värden får förekomma i DOM:en. En sida underkänns enligt detta kriterium när ID:n dupliceras på sätt som bryter de programmatiska associationer som hjälpmedelsteknik är beroende av.
De officiella undantagen i WCAG-specifikationen är minimala. Kriteriet gäller innehåll som skrivs i märkspråk; det gäller inte innehåll som genereras av skriptmiljöer där författaren inte har någon direkt kontroll över utdataformatet. I praktiken är dock utvecklare ansvariga för den slutliga renderade DOM:en oavsett vilken teknikstack som används för att producera den.
Varför det är viktigt
Duplicerade ID:n kan verka vara en mindre städfråga, men konsekvenserna för användare av hjälpmedelsteknik kan vara allvarliga. Skärmläsare som JAWS, NVDA och VoiceOver är beroende av webbläsarens tillgänglighetsträd, som i sin tur är beroende av korrekt upplösta ID-referenser för att bygga relationerna mellan gränssnittselement. När ett ID är duplicerat brukar webbläsaren bara lösa referenser till det första matchande elementet i dokumentordning och ignorerar tyst efterföljande element med samma ID.
För blinda och synnedsatta användare kan detta innebära att ett formulärfält läses upp utan sin etikett, eller att ett felmeddelande som är kopplat till ett fält via aria-describedby aldrig läses upp. Tänk på ett kassaflöde på en e‑handelssajt där fälten för leveransadress och faktureringsadress båda använder ID:n som city, zip och state. En skärmläsaranvändare som fyller i faktureringsdelen kan höra etiketten från leveransdelen i stället, vilket leder till förvirring, fel och potentiellt avbruten transaktion.
För användare med kognitiva funktionsnedsättningar innebär trasiga etikettassociationer att den synliga text de läser på skärmen inte stämmer överens med vad deras skärmläsare eller röststyrningsprogram meddelar, vilket skapar en desorienterande diskrepans som ökar den kognitiva belastningen.
För motoriskt nedsatta användare som förlitar sig på röststyrningsprogram som Dragon NaturallySpeaking kan duplicerade ID:n göra att röstkommandon som riktas mot en specifik kontroll aktiverar fel element, eftersom programvaran internt kan förlita sig på ID-baserad målstyrning.
Utöver påverkan på personer med funktionsnedsättning påverkar duplicerade ID:n även SEO: sökmotorrobotar som förlitar sig på fragmentidentifierare för att indexera specifika sidavsnitt kan indexera fel innehåll när ID:n inte är unika. Användbarheten försämras också för alla användare när interna ankarlänkar navigerar till fel plats på sidan.
Ungefär 2,2 miljarder människor världen över har någon form av synnedsättning enligt Världshälsoorganisationen. En betydande andel av dessa användare förlitar sig på skärmläsare som direkt påverkas av trasiga ID-associationer. Att säkerställa unika ID:n är en av de minst arbetskrävande och mest effektfulla åtgärderna ett utvecklingsteam kan genomföra.
Relaterade Axe-core-regler
Tre axe-core-regler motsvarar direkt de problem som tas upp i WCAG 4.1.1. Var och en riktar in sig på en specifik manifestation av problemet med duplicerade ID:n:
- duplicate-id: Den här regeln kontrollerar hela DOM:en efter alla
id-attributvärden som förekommer på mer än ett element. Den flaggar alla element utöver det första som delar ett ID, oavsett om dessa element är interaktiva eller refereras av ARIA. Detta är den bredaste av de tre reglerna och fångar strukturella överträdelser även när ingen explicit ARIA-relation är inblandad. En vanlig utlösare är komponentbaserade ramverk som renderar samma återanvändbara komponent flera gånger på en sida utan att generera unika ID:n för varje instans. - duplicate-id-active: Den här regeln snävar in fokus till duplicerade ID:n på element som är interaktiva eller fokuserbara – knappar, länkar, inmatningsfält och alla element med ett icke-negativt
tabindex. Tillgänglighetspåverkan är större här eftersom hjälpmedelsteknik och tangentbordsnavigering båda är beroende av möjligheten att entydigt identifiera en aktiv kontroll. När en skicka-knapp och en orelaterad ikon delar samma ID kan både tabbordsmeddelanden och programmatisk fokushantering sluta fungera. - duplicate-id-aria: Detta är den mest kritiska av de tre reglerna. Den flaggar duplicerade ID:n specifikt när dessa ID:n refereras av ARIA-attribut –
aria-labelledby,aria-describedby,aria-controls,aria-ownsoch liknande relationsattribut. Eftersom dessa attribut är den primära mekanismen genom vilken hjälpmedelsteknik förstår relationerna mellan element, bryter dupliceringar här direkt beräkningen av tillgängliga namn och rollrelationer. Ett underkännande exempel skulle vara två<div>-element medid='dialog-title'när en modal använderaria-labelledby='dialog-title'– skärmläsaren kommer att läsa upp det element som kommer först i DOM:en, vilket kanske inte är den avsedda dialogrubriken.
Automatiserade verktyg lämpar sig väl för att upptäcka duplicerade ID:n eftersom kontrollen är rent syntaktisk: verktyget läser DOM:en och jämför ID-värden. Ingen manuell testning krävs strikt för detta kriterium. Om ID:n däremot genereras dynamiskt efter användarinteraktion – till exempel en oändlig scroll som injicerar nytt innehåll med upprepade ID:n – kan automatiska skanningar som körs vid sidladdning missa överträdelser som bara uppträder senare. I sådana fall bör testare utlösa det dynamiska beteendet innan de kör skanningar, eller övervaka DOM:en med webbläsarens utvecklarverktyg efter interaktioner.
Hur man testar
- Automatisk skanning med axe DevTools: Öppna sidan i Chrome eller Firefox. Öppna DevTools (F12), gå till panelen axe DevTools (eller installera webbläsartillägget) och kör en fullständig sidskanning. Filtrera resultaten för reglerna duplicate-id, duplicate-id-active och duplicate-id-aria. Varje överträdelse listar de berörda elementen och deras duplicerade ID-värden. Exportera rapporten vid behov för granskningsdokumentation. För Lighthouse, kör en Lighthouse-tillgänglighetsgranskning från fliken Lighthouse i DevTools och leta efter granskningen ”Document has multiple elements with the same id”.
- Kontroll i webbläsarens DevTools-konsol: Öppna webbläsarkonsolen och kör följande JavaScript-snutt för att hitta alla duplicerade ID:n på den aktuella sidan:
const ids = [...document.querySelectorAll('[id]')].map(el => el.id); const dupes = ids.filter((id, i) => ids.indexOf(id) !== i); console.log([...new Set(dupes)]);Detta skriver ut en array med alla ID-värden som förekommer mer än en gång. En tom array betyder att inga dupliceringar finns. - Skärmläsartestning med NVDA och Firefox: Ladda sidan med NVDA igång. Navigera till ett formulär som innehåller fält med etiketter kopplade via
for/idelleraria-labelledby. Tabba genom varje fält och lyssna noga på om NVDA meddelar rätt etikett. Om ett fält meddelas utan etikett, eller med fel etikett från en annan sektion, kan en duplicerad ID vara orsaken. Upprepa denna process för alla ARIA-landmärkesregioner, modala dialoger eller widgetar som använderaria-controlselleraria-describedby. - VoiceOver och Safari på macOS: Aktivera VoiceOver (Command+F5). Använd VoiceOver-rotorn (Control+Option+U) för att öppna listan Form Controls eller Links och verifiera att varje kontroll har en unik, korrekt meddelad etikett. Navigera in i eventuella modala dialoger och bekräfta att dialogtiteln meddelas korrekt när dialogen öppnas.
- JAWS och Chrome: Med JAWS igång, öppna sidan och använd JAWS lista över formulärfält (Insert+F5) för att granska alla formulärelement och deras associerade etiketter. Verifiera att inga två fält delar samma etikettext när de borde vara distinkta.
- Testning av dynamiskt innehåll: Om sidan använder oändlig scroll, enkelsidesnavigering eller modala dialoger som injiceras via JavaScript, interagera med dessa funktioner för att ladda nytt innehåll i DOM:en och kör sedan om den automatiska skanningen eller konsolsnutten för att kontrollera dupliceringar som introduceras av det dynamiska innehållet.
Hur man åtgärdar
Duplicerade formulärfälts-ID:n över upprepade sektioner — Felaktigt
<!-- 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. -->
Duplicerade formulärfälts-ID:n över upprepade sektioner — Korrekt
<!-- 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. -->
Återanvändbar komponent renderad flera gånger — Felaktigt
<!-- 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. -->
Återanvändbar komponent renderad flera gånger — Korrekt
<!-- 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. -->
Modal dialog med duplicerad ARIA-etikettreferens — Felaktigt
<!-- 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. -->
Modal dialog med duplicerad ARIA-etikettreferens — Korrekt
<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'. -->
Vanliga misstag
- Kopiera och klistra in komponentmarkup utan att uppdatera ID:n: Utvecklare duplicerar ofta en fungerande HTML-sektion för en andra instans (ett andra adressblock, en andra flikpanel, ett andra dragspelselement) och glömmer att uppdatera alla ID-värden så att de blir unika. Etablera en namngivningskonvention som
component-name-index(t.ex.accordion-panel-1,accordion-panel-2) och upprätthåll den i kodgranskning. - Använda statiska ID:n i ramverkskomponenter utan en strategi för unika nycklar: React, Vue, Angular och liknande ramverk kan rendera samma komponent dussintals gånger på en sida. Att använda ett hårdkodat
id='search-input'inuti en återanvändbar komponent skapar lika många dupliceringar som det finns instanser. Härled alltid ID:n från props, en räknare eller ett verktyg somuseId()i React 18+. - Förlita sig på CSS-klassmålning i stället för att fixa HTML:en: Vissa utvecklare kringgår problem med duplicerade ID:n genom att byta JavaScript-selektorer från
getElementByIdtillquerySelectormed en klass, samtidigt som de lämnar de duplicerade ID:na kvar. Detta kan lösa visuellt beteende men gör ingenting för att åtgärda de trasiga associationerna i tillgänglighetsträdet. - Serversideslingor i mallar som genererar samma ID vid varje iteration: En Jinja2-, Blade- eller Twig-mall som renderar
id='item-title'inuti en{% for item in items %}-loop kommer att producera en duplicering för varje objekt i listan. Lägg alltid till loopindexet eller objektets identifierare till ID:t:id='item-title-{{ loop.index }}'. - Ignorera duplicerade ID:n i dolda eller utanför skärmen placerade element: Element med
display: noneellervisibility: hiddenfinns fortfarande i DOM:en och deras ID:n är fortfarande registrerade. En dold modalmall som delar ett ID med ett synligt element orsakar samma tolkningsfel. Använd attributethiddeneller se till att dolda mallar använder unika ID:n. - Anta att avgränsning till en Shadow DOM löser problemet: ID:n inuti inbyggd Shadow DOM är avgränsade och kolliderar inte med ID:n i light DOM eller andra shadow-rots. Många komponentbibliotek använder dock en polyfill eller ett icke-standardiserat tillvägagångssätt som inte ger verklig avgränsning. Verifiera den faktiska DOM-utmatningen i stället för att anta ramverksbeteende.
- Generera ID:n baserat på användarlevererat innehåll utan sanering eller deduplicering: Att skapa ID:n från produktnamn, artikelrubriker eller annan dynamisk text kan ge kollisioner när två objekt har samma namn (t.ex. två produkter som båda heter ”Classic” och båda genererar
id='classic'). Lägg alltid till en unik databaskey eller ett index till innehållsbaserade ID:n. - Att inte testa efter klientsidesnavigering i enkelsidesapplikationer: SPA:er som injicerar nytt ruttinnehåll i DOM:en utan en fullständig sidomladdning kan ackumulera ID:n från tidigare besökta rutter om gammalt innehåll inte avmonteras korrekt. Kör axe-skanningar efter navigering mellan rutter, inte bara vid initial laddning.
- Glömma ID:n som används i SVG-
<defs>- och<use>-element: SVG-spritemönster som definierar symboler med ID:n inuti<defs>och sedan refererar dem med<use href='#icon-arrow'>kan skapa duplicerade ID:n om samma symboldefinition inkluderas flera gånger på en sida. Centralisera SVG-spritedefinitioner och inkludera dem bara en gång. - Överse ID:n som genereras av tredjepartswidgetar, chattplugin eller analystiktskript: Tredjepartsskript injicerar ibland element med hårdkodade ID:n. Om din egen kod använder samma ID uppstår en konflikt som du kanske inte märker under utveckling. Granska hela den renderade DOM:en inklusive tredjepartsinnehåll och rapportera konflikter till leverantörer eller namnge dina egna ID:n med namnrymder för att undvika kollisioner.
Relation till Turkiets tillgänglighetsreglering
Turkiets presidentcirkulär 2025/10, publicerat i den officiella tidningen med nummer 32933 den 21 juni 2025, fastställer obligatoriska krav på webbtillgänglighet för en bred grupp offentliga och privata aktörer som är verksamma i Turkiet. Cirkuläret antar WCAG 2.2 som teknisk referensstandard, vilket gör nivå A-konformitet till den minsta juridiska basnivån för alla berörda aktörer.
WCAG 4.1.1 Parsing är ett kriterium på nivå A. Även om W3C avvecklade det i WCAG 2.2 är de axe-core-regler som upprätthåller dess primära fråga – unika ID:n – fortfarande aktiva och fortsätter att flaggas i tillgänglighetsgranskningar som genomförs mot WCAG 2.2. Turkiska tillsynsgranskningar och konformitetsbedömningar som använder automatiska skanningsverktyg kommer därför att flagga duplicate-id-överträdelser som potentiella nivå A-fel, oavsett kriteriets avvecklade status på specifikationsnivå. Organisationer som vill visa efterlevnad bör behandla överträdelser med duplicerade ID:n som blockerande problem.
De aktörer som omfattas av presidentcirkulär 2025/10 inkluderar ett brett spektrum av offentliga institutioner och privata sektorsorganisationer: alla centrala och lokala myndigheter och deras anslutna organ; banker och finansiella institutioner som regleras enligt turkisk banklagstiftning; sjukhus och privata vårdgivare; teleoperatörer som betjänar 200 000 eller fler abonnenter; e‑handelsplattformar och onlinemarknadsplatser; resebyråer och researrangörer; privata transportföretag som verkar under offentliga koncessioner; samt privatskolor och utbildningsinstitutioner som auktoriserats av utbildningsministeriet (MoNE).
Cirkuläret fastställer en stegvis tidsplan för efterlevnad. Offentliga institutioner måste uppnå full nivå A-konformitet inom ett år från cirkulärets publiceringsdatum. Privata aktörer i de berörda kategorierna har två år på sig att nå samma standard. Underlåtenhet att följa reglerna utsätter berörda aktörer för tillsynsgranskning, potentiella administrativa sanktioner och reputationsrisk på en marknad där medvetenheten om tillgänglighet ökar.
För turkiska organisationer är det särskilt relevant att åtgärda överträdelser med duplicerade ID:n i sammanhang där digitala formulär, onlinebetalningsflöden, myndighetsportaler och system för vårdbokning används. Det är just den typen av gränssnitt som mest sannolikt använder upprepade formulärsektioner, återanvändbara komponenter och tredjepartswidgetar som introducerar duplicerade ID:n. Att etablera automatiserad tillgänglighetstestning – till exempel genom att integrera axe-core i CI/CD-pipelines – som en del av utvecklingsprocessen är både en teknisk bästa praxis och en pragmatisk strategi för att upprätthålla löpande regulatorisk efterlevnad enligt cirkulärets krav.
