Kryteria sukcesu WCAG · Level A
WCAG 1.3.1: Informacje i relacje
WCAG 1.3.1 wymaga, aby informacje, struktura i relacje przekazywane za pomocą prezentacji wizualnej mogły być również określone programowo lub były dostępne w tekście, zapewniając, że użytkownicy technologii asystujących otrzymują ten sam kontekst strukturalny co użytkownicy widzący.
Co oznacza ta zasada
WCAG 1.3.1 — Informacje i relacje to kryterium poziomu A w ramach zasady Postrzegalność. Jego podstawowy wymóg jest prosty, ale ma daleko idące konsekwencje: każda informacja lub relacja przekazywana wizualnie musi być również wyrażona w sposób, który technologie asystujące mogą wykryć i przekazać użytkownikom. Jeśli w projekcie używasz wizualnych wskazówek — wcięcia, aby zasugerować listę, pogrubienia, aby oznaczyć pole wymagane, koloru, aby wskazać błąd, lub rozmiaru, aby oznaczyć nagłówek — te same semantyczne znaczenia muszą istnieć w kodzie źródłowym.
Kryterium dotyczy trzech kategorii znaczeń, które treści internetowe regularnie przekazują poprzez prezentację:
- Informacje — fakty lub dane przekazywane na stronie, takie jak to, które pola formularza są wymagane lub które komórki tabeli są ze sobą powiązane.
- Struktura — schemat organizacyjny treści, taki jak hierarchia nagłówków, listy uporządkowane lub nieuporządkowane oraz tabele danych.
- Relacje — powiązania między elementami, takie jak etykieta i jej pole wejściowe, nagłówek tabeli i jego komórki danych, czy termin i jego definicja.
Strona spełnia 1.3.1, gdy każda informacja strukturalna lub relacyjna dostępna dla użytkownika widzącego jest albo zakodowana w poprawnym, semantycznym HTML, albo ujawniona poprzez prawidłową rolę, właściwość lub stan ARIA, które technologie asystujące mogą interpretować. Strona nie spełnia wymogu, gdy struktura wizualna istnieje wyłącznie w CSS lub obrazach albo gdy znaczniki ARIA są sprzeczne ze strukturą DOM lub są w niej nieobecne.
Oficjalne wyjątki są minimalne. Kryterium nie wymaga, aby cała dekoracja wizualna niosła znaczenie semantyczne — czysto estetyczne formatowanie, takie jak dekoracyjna ramka czy kolor tła, nie musi mieć programowego odpowiednika. Jednak każde formatowanie, które użytkownik mógłby rozsądnie zinterpretować jako niosące znaczenie (gwiazdki przy polach wymaganych, pogrubione terminy w glosariuszu, ponumerowane kroki), musi mieć odpowiadający mu programowy wyraz.
Dlaczego to ma znaczenie
Informacje i relacje stanowią podstawę niemal każdej interakcji użytkownika ze stroną internetową. Gdy ta struktura jest zamknięta wyłącznie w prezentacji wizualnej, znacząca część populacji jest w praktyce wykluczona z możliwości zrozumienia treści.
Użytkownicy czytników ekranu — zazwyczaj osoby niewidome lub słabowidzące — nawigują po stronach, odwołując się do drzewa dostępności, które jest budowane na podstawie semantycznego HTML i ARIA. Gdy deweloper używa elementu <div> ostylowanego tak, by wyglądał jak nagłówek, zamiast użyć prawdziwego <h2>, użytkownik czytnika ekranu, przeskakujący między nagłówkami klawiszem H, całkowicie go pominie. Może nigdy nie znaleźć sekcji, którą ten nagłówek wprowadza. Według Światowej Organizacji Zdrowia około 2,2 miliarda ludzi na świecie żyje z jakąś formą upośledzenia wzroku, a dziesiątki milionów codziennie polegają na czytnikach ekranu.
Użytkownicy z niepełnosprawnościami poznawczymi w równym stopniu korzystają z przejrzystej struktury. Prawidłowo zagnieżdżone nagłówki, znaczące znaczniki list i opisane kontrolki formularzy zmniejszają obciążenie poznawcze, zapewniając przewidywalne wzorce. Komunikat czytnika ekranu „nagłówek poziomu 2, Produkty”, a następnie „nagłówek poziomu 3, Laptopy” tworzy mapę poznawczą strony. Płaska ściana ostylowanego tekstu bez kotwic strukturalnych jest dezorientująca dla wszystkich, a szczególnie dla użytkowników z problemami z koncentracją lub pamięcią.
Użytkownicy z niepełnosprawnościami ruchowymi, którzy polegają na nawigacji klawiaturą, przełącznikami lub oprogramowaniu sterowanym głosem, również potrzebują struktury programowej. Oprogramowanie sterowane głosem, takie jak Dragon NaturallySpeaking, generuje klikalne cele na podstawie dostępnych nazw pochodzących z etykiet i ról — pola formularza bez powiązanych etykiet po prostu nie mogą być niezawodnie wskazywane komendą głosową.
Rozważmy konkretny scenariusz: portal pacjenta szpitala wyświetla tabelę nadchodzących wizyt. Tabela używa wyrównania wizualnego i koloru tła, aby powiązać daty z lekarzami, ale elementy <th> nie mają atrybutów scope, a komórki danych nie odwołują się do nagłówków. Niewidomy użytkownik z czytnikiem ekranu słyszy odizolowane wartości komórek — „9:00”, „Dr Ayşe Kaya”, „Kardiologia” — bez możliwości ustalenia, która wartość należy do której kolumny. Może błędnie odczytać godzinę wizyty lub pojawić się w niewłaściwym oddziale. Prawidłowe użycie scope='col' w nagłówkach i atrybutów headers w komórkach uczyniłoby te relacje słyszalnymi.
Poza dostępnością, strukturalny HTML ma istotne znaczenie dla SEO. Roboty wyszukiwarek używają hierarchii nagłówków do zrozumienia tematów strony, znaczników list do identyfikowania treści wyliczeniowych oraz powiązań etykiet do zrozumienia celu formularzy. Strona, która spełnia 1.3.1, jest niemal zawsze stroną, którą wyszukiwarki mogą dokładniej przeanalizować i wyżej sklasyfikować.
Powiązane reguły axe-core
Następujące reguły axe-core odpowiadają bezpośrednio naruszeniom WCAG 1.3.1. Każda reguła dotyczy konkretnego aspektu struktury programowej lub relacji:
- aria-required-children — Sprawdza, czy elementy z określonymi rolami ARIA zawierają wymagane role potomne. Na przykład
role='list'musi zawierać elementy potomne zrole='listitem'. Bez poprawnej struktury potomnej relacja między kontenerem a jego elementami jest zerwana dla technologii asystujących. - aria-required-parent — Odwrotność powyższej: sprawdza, czy elementy z rolami wymagającymi konkretnego kontekstu nadrzędnego faktycznie mają takiego rodzica.
role='listitem', które nie znajduje się wewnątrzrole='list'lub<ul>/<ol>, jest oznaczane, ponieważ brakuje kontekstu relacji. - aria-roles — Waliduje, czy wszystkie wartości atrybutu
rolesą prawidłowymi rolami ARIA. Nieprawidłowa lub błędnie zapisana rola (np.role='heading'zamiast użycia elementu nagłówka lub całkowicie wymyślona rola) oznacza, że technologia asystująca nie otrzymuje użytecznych informacji i może całkowicie zignorować element. - definition-list — Weryfikuje, czy elementy
<dl>zawierają tylko dozwolone elementy potomne:<dt>,<dd>,<div>,<script>i<template>. Wstawienie innych elementów, takich jak<p>, bezpośrednio do<dl>unieważnia strukturę relacji termin-definicja. - dlitem — Sprawdza, czy elementy
<dt>i<dd>są używane wyłącznie wewnątrz elementów<dl>. Użycie tych elementów poza wymagającym je kontekstem nadrzędnym niszczy semantyczne znaczenie pary termin-definicja. - heading-order — Oznacza poziomy nagłówków, które są pominięte w zarysie dokumentu (np. przeskok z
<h2>do<h4>). Choć nie zawsze jest to ścisłe naruszenie, pomijanie poziomów wprowadza technologie asystujące w błąd co do hierarchicznej struktury strony i dezorientuje użytkowników nawigujących po nagłówkach. - label — Weryfikuje, czy każde pole formularza ma programowo powiązaną etykietę, poprzez
<label for='...'>,aria-label,aria-labelledbylub otaczający element<label>. Pole bez dostępnej etykiety pozbawia użytkowników niewidomych i korzystających ze sterowania głosem informacji potrzebnych do zrozumienia, co należy wprowadzić. - list — Zapewnia, że elementy
<ul>i<ol>zawierają jako bezpośrednie dzieci wyłącznie elementy<li>(plus<script>i<template>). Nieprawidłowe elementy potomne psują strukturę listy, której czytniki ekranu używają do ogłaszania liczby i pozycji elementów. - listitem — Sprawdza, czy elementy
<li>są używane wyłącznie wewnątrz kontenerów<ul>,<ol>lubrole='list'. Osierocone elementy list tracą całkowicie swoje semantyczne znaczenie. - scope-attr-valid — Waliduje, czy atrybut
scopew elementach<th>zawiera tylko dozwolone wartości:col,row,colgrouplubrowgroup. Nieprawidłowa lub brakująca wartość scope w złożonej tabeli danych oznacza, że czytniki ekranu nie mogą wiarygodnie ogłaszać, który nagłówek dotyczy danej komórki danych. - td-headers-attr — Sprawdza, czy gdy komórki danych używają atrybutu
headers, każdy odwoływany identyfikator faktycznie istnieje w tej samej tabeli i należy do komórki nagłówka. Zerwane lub brakujące odwołania zrywają programową relację między danymi a ich opisowym nagłówkiem, pozostawiając użytkowników czytników ekranu bez kontekstu.
Należy pamiętać, że narzędzia automatyczne, takie jak axe-core, nie są w stanie wykryć każdego naruszenia 1.3.1. Na przykład deweloper może użyć wizualnie ostylowanego <div> z role='list' i poprawnie zbudowanymi potomnymi elementami role='listitem' — axe uzna to za poprawne — ale tester ludzki może odkryć, że wizualne wcięcia sugerują zagnieżdżoną podlistę, która nie jest odzwierciedlona w strukturze ARIA. Zawsze gdy hierarchia wizualna jest złożona, ręczna inspekcja i testy z czytnikiem ekranu są niezbędnym uzupełnieniem skanowania automatycznego.
Jak testować
- Automatyczne skanowanie za pomocą axe DevTools lub Lighthouse: Zainstaluj rozszerzenie przeglądarki axe DevTools (Chrome lub Firefox). Otwórz testowaną stronę, otwórz DevTools, przejdź do zakładki axe i uruchom skan całej strony. Przefiltruj wyniki według tagu
wcag131lub przejrzyj wszystkie problemy oznaczone jako „Info and Relationships”. Szukaj w szczególności naruszeń jedenastu wymienionych powyżej reguł axe. W Lighthouse (panel Audits w Chrome DevTools) uruchom audyt dostępności i sprawdź kategorię „Accessibility” pod kątem błędów związanych z kolejnością nagłówków, etykietami i listami. Zanotuj wszystkie oznaczone elementy i ich selektory DOM do naprawy. - Ręczny przegląd struktury nagłówków: Użyj rozszerzenia przeglądarki HeadingsMap lub panelu „Headings” w axe DevTools, aby zobaczyć pełny zarys nagłówków na stronie. Zweryfikuj, że zarys jest logiczny i hierarchiczny — powinien czytać się jak dobrze zbudowany spis treści. Upewnij się, że żadne poziomy nagłówków nie są pominięte i że tekst nagłówków jest znaczący, a nie tylko wizualnym stylowaniem zastosowanym do elementów, które nie są nagłówkami.
- Weryfikacja etykiet formularzy: Przejdź klawiszem Tab przez każdy interaktywny element formularza na stronie. Dla każdego elementu input, select i textarea upewnij się, że widoczna etykieta jest obecna i że jest programowo powiązana (sprawdź element w DevTools i poszukaj pasującej pary
for/idlubaria-label/aria-labelledby). Użyj drzewa dostępności w Chrome DevTools (panel Elements → zakładka Accessibility), aby potwierdzić obliczoną dostępną nazwę każdej kontrolki. - Testy z czytnikiem ekranu NVDA + Firefox: Uruchom NVDA i otwórz stronę w Firefox. Naciśnij H, aby przechodzić między nagłówkami i zweryfikuj, że ogłaszane poziomy nagłówków odpowiadają hierarchii wizualnej. Naciśnij F, aby przechodzić między polami formularza i potwierdź, że etykieta każdego pola jest ogłaszana. Naciśnij T, aby nawigować po tabelach i strzałkami przechodź między komórkami, słuchając ogłaszanych nagłówków. Naciśnij L, aby przechodzić między listami i potwierdź, że liczba elementów jest ogłaszana.
- Testy z czytnikiem ekranu VoiceOver + Safari (macOS/iOS): Włącz VoiceOver (Cmd+F5 w macOS). Otwórz Rotor (Ctrl+Option+U) i sprawdź sekcje Headings, Links, Form Controls i Tables. Potwierdź, że wszystkie elementy strukturalne pojawiają się w Rotorze i że ich ogłaszane nazwy są znaczące i poprawne.
- Testy z czytnikiem ekranu JAWS + Chrome: Otwórz JAWS i stronę w Chrome. Użyj listy nagłówków JAWS (Insert+F6), aby przejrzeć drzewo nagłówków. Użyj Insert+F5 dla pól formularza, aby zweryfikować powiązania etykiet. Nawiguj po tabelach za pomocą klawiszy strzałek i potwierdź, że JAWS ogłasza nagłówki kolumn i wierszy dla każdej komórki danych.
- Sprawdzenie relacji nagłówków tabel: Zidentyfikuj wszystkie tabele danych na stronie. Dla prostych tabel zweryfikuj, że elementy
<th>mają odpowiednie atrybutyscope. Dla złożonych tabel z wielopoziomowymi nagłówkami sprawdź, czy komórki danych używają atrybutuheaders, odwołując się do właściwych wartościid. Wizualnie prześledź każdą komórkę do jej logicznych nagłówków wiersza i kolumny, a następnie potwierdź, że ta sama ścieżka jest odzwierciedlona w kodzie.
Jak naprawić
Wizualne nagłówki zaimplementowane jako ostylowane divy — niepoprawne
<!-- Heading conveyed only through CSS font-size and font-weight -->
<div class='section-title'>Our Services</div>
<div class='subsection-title'>Web Development</div>
<p>We build fast, accessible websites.</p>
Wizualne nagłówki zaimplementowane jako ostylowane divy — poprawne
<!-- Semantic heading elements expose hierarchy to assistive technologies -->
<h2>Our Services</h2>
<h3>Web Development</h3>
<p>We build fast, accessible websites.</p>
Pole formularza bez powiązanej etykiety — niepoprawne
<!-- The placeholder is not a substitute for a label; it disappears on input -->
<p>Email Address *</p>
<input type='email' placeholder='Enter your email' />
Pole formularza bez powiązanej etykiety — poprawne
<!-- The for attribute ties the label to the input by matching id -->
<label for='email'>Email Address <span aria-hidden='true'>*</span><span class='sr-only'>(required)</span></label>
<input type='email' id='email' aria-required='true' />
Tabela danych bez atrybutów scope — niepoprawne
<!-- Headers have no scope; screen readers cannot associate columns with data -->
<table>
<tr>
<th>Tarih</th>
<th>Doktor</th>
<th>Klinik</th>
</tr>
<tr>
<td>15 Temmuz 2025</td>
<td>Dr. Ayşe Kaya</td>
<td>Kardiyoloji</td>
</tr>
</table>
Tabela danych bez atrybutów scope — poprawne
<!-- scope='col' tells screen readers each th describes its entire column -->
<table>
<caption>Yaklaşan Randevular</caption>
<thead>
<tr>
<th scope='col'>Tarih</th>
<th scope='col'>Doktor</th>
<th scope='col'>Klinik</th>
</tr>
</thead>
<tbody>
<tr>
<td>15 Temmuz 2025</td>
<td>Dr. Ayşe Kaya</td>
<td>Kardiyoloji</td>
</tr>
</tbody>
</table>
Elementy listy użyte poza kontenerem listy — niepoprawne
<!-- li elements without a parent ul or ol have no semantic meaning -->
<div class='features'>
<li>Fast performance</li>
<li>WCAG compliant</li>
<li>Mobile friendly</li>
</div>
Elementy listy użyte poza kontenerem listy — poprawne
<!-- Wrapping ul gives screen readers item count and navigation context -->
<ul class='features'>
<li>Fast performance</li>
<li>WCAG compliant</li>
<li>Mobile friendly</li>
</ul>
Typowe błędy
- Używanie samego CSS
font-sizeifont-weight, aby stworzyć wizualny wygląd nagłówków na elementach<div>lub<span>, bez dodaniarole='heading'iaria-levellub bez konwersji na rzeczywiste elementy<h1>–<h6>— czytniki ekranu nie mogą wykryć ich jako nagłówków, po których można nawigować. - Używanie tekstu
placeholderjako jedynej etykiety dla pól formularza, co powoduje, że etykieta znika, gdy tylko użytkownik zacznie pisać, pozostawiając pole nieopisane na czas wprowadzania danych — zawsze łącz pola z trwałym elementem<label>. - Oznaczanie pól wymaganych czerwoną gwiazdką (*), która jest wyjaśniona wyłącznie w legendzie wizualnej na górze formularza, bez dodania
aria-required='true'lub uwzględnienia słowa „wymagane” w programowej etykiecie, tak aby użytkownicy czytników ekranu otrzymali tę samą informację. - Stosowanie
list-style: nonew CSS do elementu<ul>bez świadomości, że niektóre czytniki ekranu (szczególnie Safari + VoiceOver) mogą przestać ogłaszać ten element jako listę — jeśli semantyka listy jest istotna, dodaj expliciterole='list', aby ją zachować. - Pomijanie poziomów nagłówków — na przykład umieszczenie
<h4>bezpośrednio po<h2>, ponieważ projektant chciał mniejszego tekstu — zamiast użycia właściwego poziomu nagłówka i kontrolowania wyglądu wizualnego za pomocą CSS. - Budowanie złożonych tabel danych ze scalonymi komórkami (
colspan/rowspan) bez dodania atrybutuheadersw komórkach danych, co uniemożliwia użytkownikom czytników ekranu ustalenie, który nagłówek dotyczy niejednoznacznej scalonej komórki. - Używanie elementów
<table>do celów layoutu, a następnie dodawanierole='presentation'w sposób niespójny — niektóre komórki nadal zawierają nagłówki, które są ogłaszane poza kontekstem, co dezorientuje użytkowników, którzy nie widzą, że tabela jest czysto dekoracyjna. - Opakowywanie pary
<dt>/<dd>wewnątrz<p>lub<div>, który jest bezpośrednim potomkiem<dl>, bez świadomości, że w HTML5 wewnątrz<dl>dozwolone są tylko opakowania<div>i że mieszanie innych elementów blokowych niszczy strukturę listy definicji. - Dodawanie
aria-labelledbydo pola wejściowego, które odwołuje się do identyfikatora nieistniejącego w DOM lub odwołuje się do identyfikatora elementu, który nie zawiera tekstu — obliczona dostępna nazwa staje się pusta, a pole jest w praktyce nieopisane dla technologii asystujących. - Zakładanie, że skoro strona wygląda poprawnie wizualnie i osiąga wynik Lighthouse powyżej 90, to jest zgodna z 1.3.1 — narzędzia automatyczne nie są w stanie wykryć każdego naruszenia strukturalnego, takiego jak wizualne relacje zagnieżdżenia, które nie są odzwierciedlone w hierarchii ról ARIA, co wymaga obowiązkowej weryfikacji ręcznej i testów z czytnikiem ekranu.
Związek z tureckimi regulacjami dotyczącymi dostępności
Prezydencki okólnik Turcji 2025/10, opublikowany w Dzienniku Urzędowym nr 32933 w dniu 21 czerwca 2025 r., ustanawia obowiązkowe wymogi dostępności stron internetowych, zgodne z WCAG 2.2, dla szerokiego zakresu podmiotów działających w Turcji. WCAG 1.3.1 jest kryterium poziomu A, co oznacza, że znajduje się na podstawowym poziomie zgodności — minimalnym akceptowalnym poziomie dostępności — i dlatego jest w pełni obowiązkowe dla wszystkich podmiotów objętych okólnikiem.
Okólnik definiuje dwa harmonogramy zgodności. Instytucje publiczne — w tym centralne organy administracji, gminy, uniwersytety państwowe i szpitale publiczne — muszą osiągnąć pełną zgodność z poziomem A w ciągu jednego roku od wejścia okólnika w życie. Podmioty sektora prywatnego objęte regulacją mają dwuletnie okno na dostosowanie się. Obowiązek nie jest jednak opcjonalny dla żadnej z grup: brak zgodności naraża podmioty objęte regulacją na kontrolę organów nadzoru i potencjalne działania egzekucyjne.
Podmioty sektora prywatnego wyraźnie objęte okólnikiem obejmują platformy e-commerce, banki i instytucje finansowe, prywatne szpitale i świadczeniodawców opieki zdrowotnej, przedsiębiorstwa telekomunikacyjne z 200,000 lub większą liczbą abonentów, licencjonowane biura podróży, prywatne firmy transportowe oraz szkoły prywatne działające na podstawie zezwolenia Ministerstwa Edukacji Narodowej (MoNE). Każdy z tych podmiotów prowadzący publicznie dostępną stronę internetową lub mobilną aplikację webową musi zapewnić spełnienie 1.3.1 we wszystkich swoich zasobach cyfrowych.
Z praktycznego punktu widzenia 1.3.1 jest jednym z najbardziej wpływowych kryteriów poziomu A, ponieważ reguluje fundamentalną strukturę strony. Turecka strona e-commerce, której strony kategorii produktów używają ostylowanych elementów <div> jako nagłówków, której pola formularza w procesie zakupu nie mają powiązanych etykiet lub której podsumowanie zamówienia jest niestrukturalną tabelą bez atrybutów scope, w sposób kompleksowy nie spełnia 1.3.1. Dostosowanie nie jest jedynie obowiązkiem prawnym — bezpośrednio poprawia doświadczenie szacunkowo 700,000 lub więcej osób niewidomych i słabowidzących w Turcji, które polegają na technologiach asystujących, aby robić zakupy, korzystać z bankowości, opieki zdrowotnej i usług administracji publicznej online.
Organizacjom, które chcą wykazać zgodność, zaleca się przeprowadzanie zarówno automatycznych skanów axe-core, jak i ręcznych audytów z użyciem czytników ekranu, obejmujących pełne spektrum ich treści cyfrowych. Dostępność strukturalna — fundament, który egzekwuje 1.3.1 — powinna być wbudowana w systemy projektowe i biblioteki komponentów, tak aby zgodność była utrzymywana w miarę tworzenia i aktualizowania treści, a nie traktowana jako jednorazowe ćwiczenie naprawcze.
