Kryteria sukcesu WCAG · Level A
WCAG 4.1.1: Parsowanie (przestarzałe w WCAG 2.2)
WCAG 4.1.1 Parsowanie wymaga, aby treści internetowe były wolne od poważnych błędów HTML/XML — takich jak zduplikowane identyfikatory — które mogłyby spowodować, że technologie asystujące błędnie zinterpretują stronę lub nie zdołają jej przetworzyć. Chociaż kryterium to jest przestarzałe w WCAG 2.2, leżące u jego podstaw reguły axe-core pozostają aktywne, a naruszenia nadal wskazują na realne ryzyko w zakresie dostępności.
Co Oznacza Ta Zasada
WCAG 4.1.1 Parsing została pierwotnie zaprojektowana, aby zapewnić, że agenci użytkownika, w tym przeglądarki i technologie asystujące, mogą dokładnie analizować i interpretować treści internetowe. Kryterium wymagało, aby strony tworzone w językach znaczników, takich jak HTML lub XML, spełniały cztery warunki strukturalne: elementy muszą mieć kompletne znaczniki początkowe i końcowe; elementy muszą być zagnieżdżone zgodnie ze swoją specyfikacją; elementy nie mogą zawierać zduplikowanych atrybutów; oraz wszystkie identyfikatory (ID) użyte w treści muszą być unikalne.
W WCAG 2.2 W3C formalnie wycofało to kryterium. Uzasadnieniem było to, że nowoczesne przeglądarki stały się bardzo odporne na niepoprawny HTML, automatycznie korygując większość błędów strukturalnych, zanim w ogóle trafią one do drzewa dostępności. W rezultacie wiele pierwotnych obaw — takich jak niezamknięte znaczniki czy nieprawidłowo zagnieżdżone elementy — nie powoduje już praktycznej szkody dla technologii asystujących we współczesnych środowiskach.
Wycofanie nie oznacza jednak, że problemy, na które wskazywało to kryterium, całkowicie zniknęły. W3C wyraźnie zaznacza, że zduplikowane atrybuty ID pozostają istotnym problemem dostępności. Gdy dwa lub więcej elementów współdzieli tę samą wartość id, przeglądarka musi podjąć arbitralną decyzję, który element powiązać z odwołaniami ARIA, powiązaniami etykiet lub linkami z fragmentami. Ta niejednoznaczność może powodować, że czytniki ekranu ogłaszają nieprawidłową treść, pomijają interaktywne kontrolki lub w ogóle nie ujawniają etykiet pól formularza. Warunek zaliczenia kryterium najlepiej rozumieć dziś jako: w DOM nie występują zduplikowane wartości ID. Strona nie spełnia tego kryterium, gdy identyfikatory są zduplikowane w sposób, który psuje powiązania programistyczne, na których polegają technologie asystujące.
Oficjalne wyjątki w specyfikacji WCAG są minimalne. Kryterium ma zastosowanie do treści tworzonej w językach znaczników; nie dotyczy treści generowanej przez środowiska skryptowe, w których autor nie ma bezpośredniej kontroli nad formatem wyjściowym. W praktyce jednak deweloperzy są odpowiedzialni za ostateczny wyrenderowany DOM niezależnie od stosowanego stosu technologicznego.
Dlaczego To Ma Znaczenie
Zduplikowane ID mogą wydawać się drobną kwestią porządkową, ale ich konsekwencje dla użytkowników technologii asystujących mogą być poważne. Czytniki ekranu, takie jak JAWS, NVDA i VoiceOver, polegają na drzewie dostępności przeglądarki, które z kolei zależy od poprawnie rozwiązywanych odwołań ID, aby budować relacje między elementami interfejsu. Gdy ID jest zduplikowane, przeglądarka zazwyczaj rozwiązuje odwołania tylko do pierwszego pasującego elementu w kolejności dokumentu, po cichu ignorując kolejne elementy z tym samym ID.
Dla użytkowników niewidomych i słabowidzących może to oznaczać, że pole formularza jest ogłaszane bez swojej etykiety lub że komunikat o błędzie powiązany z polem za pomocą aria-describedby nigdy nie zostanie odczytany. Rozważ formularz zamówienia na stronie e-commerce, gdzie pola adresu wysyłki i adresu rozliczeniowego używają tych samych ID, takich jak city, zip i state. Użytkownik czytnika ekranu wypełniający sekcję rozliczeniową może usłyszeć etykietę z sekcji wysyłki, co prowadzi do dezorientacji, błędów i potencjalnego porzucenia transakcji.
Dla użytkowników z niepełnosprawnościami poznawczymi zerwane powiązania etykiet oznaczają, że widoczny tekst, który czytają na ekranie, nie odpowiada temu, co ogłasza ich czytnik ekranu lub oprogramowanie do sterowania głosem, tworząc dezorientujące rozłączenie, które zwiększa obciążenie poznawcze.
Dla użytkowników z niepełnosprawnością ruchową polegających na oprogramowaniu sterowanym głosem, takim jak Dragon NaturallySpeaking, zduplikowane ID mogą powodować, że komendy głosowe kierowane do konkretnej kontrolki aktywują niewłaściwy element, ponieważ oprogramowanie może wewnętrznie polegać na adresowaniu opartym na ID.
Poza wpływem na osoby z niepełnosprawnościami, zduplikowane ID wpływają również na SEO: roboty wyszukiwarek, które polegają na identyfikatorach fragmentów do indeksowania konkretnych sekcji strony, mogą indeksować nieprawidłową treść, gdy ID nie są unikalne. Użyteczność jest również obniżona dla wszystkich użytkowników, gdy linki kotwiczące w obrębie strony prowadzą do niewłaściwego miejsca na stronie.
Około 2,2 miliarda ludzi na świecie ma jakąś formę upośledzenia wzroku według Światowej Organizacji Zdrowia. Znaczna część tych użytkowników polega na czytnikach ekranu, które są bezpośrednio dotknięte zerwanymi powiązaniami ID. Zapewnienie unikalności ID jest jednym z najmniej pracochłonnych, a jednocześnie najbardziej efektywnych działań naprawczych, jakie może wdrożyć zespół deweloperski.
Powiązane Zasady Axe-core
Trzy zasady axe-core bezpośrednio odpowiadają na problemy poruszone w WCAG 4.1.1. Każda z nich celuje w konkretne przejawy problemu zduplikowanych ID:
- duplicate-id: Ta zasada sprawdza cały DOM pod kątem dowolnej wartości atrybutu
id, która pojawia się na więcej niż jednym elemencie. Oznacza wszystkie elementy poza pierwszym, które współdzielą ID, niezależnie od tego, czy są interaktywne lub referencjonowane przez ARIA. Jest to najszersza z trzech zasad i wychwytuje naruszenia strukturalne nawet wtedy, gdy nie występuje żaden jawny związek ARIA. Częstym wyzwalaczem są frameworki komponentowe, które renderują ten sam wielokrotnego użytku komponent wiele razy na stronie bez generowania unikalnych ID dla każdej instancji. - duplicate-id-active: Ta zasada zawęża zakres do zduplikowanych ID na elementach interaktywnych lub fokusowalnych — przyciskach, linkach, polach wejściowych oraz dowolnym elemencie z nieujemnym
tabindex. Wpływ na dostępność jest tu podwyższony, ponieważ technologie asystujące i nawigacja klawiaturą polegają na możliwości jednoznacznej identyfikacji aktywnej kontrolki. Gdy przycisk „submit” i niepowiązana ikona współdzielą to samo ID, zarówno ogłaszanie kolejności tabulacji, jak i programistyczne zarządzanie fokusem mogą przestać działać. - duplicate-id-aria: Jest to najbardziej krytyczna z trzech zasad. Oznacza zduplikowane ID konkretnie wtedy, gdy te ID są referencjonowane przez atrybuty ARIA —
aria-labelledby,aria-describedby,aria-controls,aria-ownsi podobne atrybuty relacji. Ponieważ te atrybuty są głównym mechanizmem, za pomocą którego technologie asystujące rozumieją relacje między elementami, duplikaty w tym miejscu bezpośrednio psują obliczanie dostępnej nazwy i relacje ról. Przykładem niezaliczenia byłoby istnienie dwóch elementów<div>zid='dialog-title', gdy modal używaaria-labelledby='dialog-title'— czytnik ekranu ogłosi ten element, który pojawia się pierwszy w DOM, co może nie być zamierzonym nagłówkiem dialogu.
Narzędzia automatyczne bardzo dobrze nadają się do wykrywania zduplikowanych ID, ponieważ sprawdzenie jest czysto składniowe: narzędzie odczytuje DOM i porównuje wartości ID. Dla tego kryterium nie jest bezwzględnie wymagana ręczna weryfikacja. Jeśli jednak ID są generowane dynamicznie po interakcji użytkownika — na przykład nieskończone przewijanie, które wstrzykuje nową treść z powtarzającymi się ID — automatyczne skany uruchamiane przy ładowaniu strony mogą nie wychwycić naruszeń, które pojawiają się dopiero później. W takich przypadkach testerzy powinni wywołać zachowanie dynamiczne przed uruchomieniem skanów lub monitorować DOM za pomocą narzędzi deweloperskich przeglądarki po interakcjach.
Jak Testować
- Automatyczny skan za pomocą axe DevTools: Otwórz stronę w Chrome lub Firefox. Otwórz DevTools (F12), przejdź do panelu axe DevTools (lub zainstaluj rozszerzenie przeglądarki) i uruchom skan całej strony. Przefiltruj wyniki dla zasad duplicate-id, duplicate-id-active i duplicate-id-aria. Każde naruszenie będzie zawierać listę dotkniętych elementów i ich zduplikowanych wartości ID. Wyeksportuj raport, jeśli jest potrzebny do dokumentacji audytu. Dla Lighthouse uruchom audyt dostępności Lighthouse z karty Lighthouse w DevTools i poszukaj audytu „Document has multiple elements with the same id”.
- Sprawdzenie w konsoli narzędzi deweloperskich przeglądarki: Otwórz konsolę przeglądarki i uruchom następujący fragment JavaScript, aby znaleźć wszystkie zduplikowane ID na bieżącej stronie:
const ids = [...document.querySelectorAll('[id]')].map(el => el.id); const dupes = ids.filter((id, i) => ids.indexOf(id) !== i); console.log([...new Set(dupes)]);Spowoduje to wypisanie tablicy wszystkich wartości ID, które pojawiają się więcej niż raz. Pusta tablica oznacza brak duplikatów. - Testowanie z czytnikiem ekranu NVDA i Firefox: Załaduj stronę z uruchomionym NVDA. Przejdź do formularza zawierającego pola z etykietami powiązanymi za pomocą
for/idlubaria-labelledby. Przechodź tabulatorem przez każde pole i uważnie słuchaj, czy NVDA ogłasza poprawną etykietę. Jeśli pole jest ogłaszane bez etykiety lub z niewłaściwą etykietą z innej sekcji, przyczyną może być zduplikowane ID. Powtórz ten proces dla regionów orientacyjnych ARIA, okien modalnych lub widżetów, które używająaria-controlslubaria-describedby. - VoiceOver i Safari na macOS: Włącz VoiceOver (Command+F5). Użyj rotora VoiceOver (Control+Option+U), aby otworzyć listę kontrolek formularza lub linków i sprawdź, czy każda kontrolka ma unikalną, poprawnie ogłaszaną etykietę. Wejdź do dowolnych okien modalnych i potwierdź, że tytuł dialogu jest poprawnie ogłaszany po otwarciu okna.
- JAWS i Chrome: Z uruchomionym JAWS otwórz stronę i użyj listy pól formularza JAWS (Insert+F5), aby przejrzeć wszystkie elementy formularza i ich powiązane etykiety. Upewnij się, że żadne dwa pola nie współdzielą tego samego tekstu etykiety, jeśli powinny być rozróżnialne.
- Testowanie treści dynamicznej: Jeśli strona używa nieskończonego przewijania, nawigacji jednostronicowej lub okien modalnych wstrzykiwanych za pomocą JavaScript, wejdź w interakcję z tymi funkcjami, aby załadować nową treść do DOM, a następnie ponownie uruchom automatyczny skan lub fragment konsoli, aby sprawdzić duplikaty wprowadzone przez treść dynamiczną.
Jak Naprawić
Zduplikowane ID pól formularza w powtarzających się sekcjach — Niepoprawne
<!-- 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. -->
Zduplikowane ID pól formularza w powtarzających się sekcjach — Poprawne
<!-- 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. -->
Wielokrotnie renderowany komponent wielokrotnego użytku — Niepoprawne
<!-- 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. -->
Wielokrotnie renderowany komponent wielokrotnego użytku — Poprawne
<!-- 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. -->
Okno modalne ze zduplikowanym odwołaniem etykiety ARIA — Niepoprawne
<!-- 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. -->
Okno modalne ze zduplikowanym odwołaniem etykiety ARIA — Poprawne
<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'. -->
Typowe Błędy
- Kopiowanie i wklejanie znaczników komponentu bez aktualizacji ID: Deweloperzy często duplikują działającą sekcję HTML dla drugiej instancji (drugi blok adresowy, drugi panel zakładki, drugi element akordeonu) i zapominają zaktualizować wszystkie wartości ID tak, aby były unikalne. Ustal konwencję nazewniczą, taką jak
component-name-index(np.accordion-panel-1,accordion-panel-2) i egzekwuj ją w ramach przeglądu kodu. - Używanie statycznych ID w komponentach frameworków bez strategii unikalnych kluczy: React, Vue, Angular i podobne frameworki mogą renderować ten sam komponent dziesiątki razy na jednej stronie. Użycie zakodowanego na stałe
id='search-input'wewnątrz komponentu wielokrotnego użytku utworzy tyle duplikatów, ile jest instancji. Zawsze wyprowadzaj ID z propsów, licznika lub narzędzia takiego jakuseId()w React 18+. - Poleganie na selektorach klas CSS zamiast naprawy HTML: Niektórzy deweloperzy obchodzą problem zduplikowanych ID, zmieniając selektory JavaScript z
getElementByIdnaquerySelectorz klasą, pozostawiając zduplikowane ID na miejscu. Może to naprawić zachowanie wizualne, ale nie rozwiązuje zerwanych powiązań w drzewie dostępności. - Pętle szablonów po stronie serwera generujące to samo ID przy każdej iteracji: Szablon Jinja2, Blade lub Twig, który renderuje
id='item-title'wewnątrz pętli{% for item in items %}, wygeneruje jeden duplikat dla każdego elementu na liście. Zawsze dołączaj indeks pętli lub identyfikator elementu do ID:id='item-title-{{ loop.index }}'. - Ignorowanie zduplikowanych ID w elementach ukrytych lub poza ekranem: Elementy z
display: nonelubvisibility: hiddennadal są obecne w DOM i ich ID są nadal zarejestrowane. Ukryty szablon modala, który współdzieli ID z widocznym elementem, spowoduje te same błędy analizy. Używaj atrybutuhiddenlub upewnij się, że ukryte szablony używają unikalnych ID. - Założenie, że zakres Shadow DOM rozwiązuje problem: ID wewnątrz natywnego Shadow DOM są ograniczone zakresem i nie kolidują z ID w light DOM ani w innych korzeniach shadow. Jednak wiele bibliotek komponentów używa polyfilli lub niestandardowego podejścia, które nie zapewnia prawdziwego zakresu. Weryfikuj rzeczywisty wynik DOM zamiast zakładać zachowanie frameworka.
- Generowanie ID na podstawie treści dostarczonej przez użytkownika bez sanityzacji lub deduplikacji: Tworzenie ID z nazw produktów, tytułów artykułów lub innego tekstu dynamicznego może prowadzić do kolizji, gdy dwa elementy mają tę samą nazwę (np. dwa produkty o nazwie „Classic” generujące oba
id='classic'). Zawsze dołączaj unikalny klucz bazy danych lub indeks do ID pochodzących z treści. - Brak testów po nawigacji po stronie klienta w aplikacjach jednostronicowych: SPA, które wstrzykują nową treść trasy do DOM bez pełnego przeładowania strony, mogą kumulować ID z wcześniej odwiedzonych tras, jeśli stara treść nie jest poprawnie odmontowywana. Uruchamiaj skany axe po nawigacji między trasami, a nie tylko przy początkowym ładowaniu.
- Zapominanie o ID używanych w elementach SVG
<defs>i<use>: Wzorce sprite’ów SVG, które definiują symbole z ID wewnątrz<defs>, a następnie referencjonują je za pomocą<use href='#icon-arrow'>, mogą tworzyć zduplikowane ID, jeśli ta sama definicja symbolu jest dołączona wielokrotnie na stronie. Scentralizuj definicje sprite’ów SVG i dołączaj je tylko raz. - Przeoczenie ID generowanych przez widżety firm trzecich, wtyczki czatu lub skrypty analityczne: Skrypty firm trzecich czasami wstrzykują elementy z zakodowanymi na stałe ID. Jeśli Twój własny kod używa tego samego ID, powstaje konflikt, którego możesz nie zauważyć podczas developmentu. Audytuj cały wyrenderowany DOM, w tym treści firm trzecich, i zgłaszaj konflikty dostawcom lub przestrzegaj nazw własnych ID, aby uniknąć kolizji.
Związek z Przepisami Dostępności w Turcji
Turecka Okrężnica Prezydencka 2025/10, opublikowana w Dzienniku Urzędowym nr 32933 w dniu 21 czerwca 2025 r., ustanawia obowiązkowe wymagania dotyczące dostępności stron internetowych dla szerokiego zakresu podmiotów publicznych i prywatnych działających w Turcji. Okrężnica przyjmuje WCAG 2.2 jako techniczny standard referencyjny, czyniąc zgodność na poziomie A minimalnym wymogiem prawnym dla wszystkich objętych podmiotów.
WCAG 4.1.1 Parsing jest kryterium poziomu A. Mimo że W3C wycofało je w WCAG 2.2, zasady axe-core egzekwujące jego główny problem — unikalne ID — pozostają aktywne i nadal są oznaczane w audytach dostępności prowadzonych w oparciu o WCAG 2.2. Tureckie audyty regulacyjne i przeglądy zgodności, które używają narzędzi do automatycznego skanowania, będą zatem oznaczać naruszenia duplicate-id jako potencjalne niepowodzenia na poziomie A, niezależnie od statusu kryterium jako wycofanego na poziomie specyfikacji. Organizacje dążące do wykazania zgodności powinny traktować naruszenia związane z duplikacją ID jako kwestie blokujące.
Podmioty objęte Okrężnicą Prezydencką 2025/10 obejmują szeroki zakres instytucji publicznych i organizacji sektora prywatnego: wszystkie centralne i lokalne organy administracji oraz ich jednostki zależne; banki i instytucje finansowe regulowane na mocy tureckiego prawa bankowego; szpitale i prywatnych świadczeniodawców opieki zdrowotnej; operatorów telekomunikacyjnych obsługujących 200 000 lub więcej abonentów; platformy e-commerce i rynki internetowe; biura podróży i organizatorów wycieczek; prywatne firmy transportowe działające na podstawie koncesji publicznych; oraz prywatne szkoły i instytucje edukacyjne upoważnione przez Ministerstwo Edukacji Narodowej (MoNE).
Okrężnica ustanawia stopniowy harmonogram osiągania zgodności. Instytucje publiczne muszą osiągnąć pełną zgodność na poziomie A w ciągu jednego roku od daty publikacji okrężnicy. Podmioty sektora prywatnego w objętych kategoriach mają dwa lata na osiągnięcie tego samego standardu. Brak zgodności naraża objęte podmioty na kontrolę regulacyjną, potencjalne sankcje administracyjne oraz ryzyko reputacyjne na rynku, który coraz bardziej zwraca uwagę na dostępność.
Dla tureckich organizacji usuwanie naruszeń związanych ze zduplikowanymi ID jest szczególnie istotne w kontekstach, w których występują formularze cyfrowe, przepływy płatności online, portale usług publicznych i systemy rezerwacji opieki zdrowotnej. To właśnie te typy interfejsów najczęściej wykorzystują powtarzające się sekcje formularzy, komponenty wielokrotnego użytku i integracje widżetów firm trzecich, które wprowadzają zduplikowane ID. Ustanowienie automatycznego testowania dostępności — na przykład poprzez integrację axe-core z potokami CI/CD — jako części procesu deweloperskiego jest zarówno najlepszą praktyką techniczną, jak i pragmatyczną strategią utrzymania bieżącej zgodności regulacyjnej w ramach wymogów okrężnicy.
