WCAG 2.1: liczba kryteriów i skan axe-core
To materiał do artykułu WCAG 2.1: 4 zasady, poziom AA i różnice z 2.0 i 2.2. We wrześniu 2026 zrobiłem trzy małe pomiary: policzyłem kryteria sukcesu w każdej wersji WCAG, porównałem polską ustawę o dostępności z WCAG 2.1 i puściłem automatyczny skan na dziesięciu stronach mojej witryny. Żaden z nich nie ocenia zgodności strony z WCAG, także mojej. Angielska wersja tej notatki to methodology.md.
Kryteria według wersji i poziomu
Skrypt pobiera trzy rekomendacje W3C (/TR/WCAG20/, /TR/WCAG21/ i /TR/WCAG22/) i wyciąga z nich każde kryterium sukcesu z jego poziomem. Te adresy zawsze prowadzą do najnowszego wydania danej wersji, w przypadku WCAG 2.1 było to wydanie z 2025 roku, a W3C zaznacza, że kolejne wydania mają te same kryteria. Kryterium 4.1.1 Parsing policzyłem w WCAG 2.2 jako usunięte, bo specyfikacja oznacza je tam jako „Obsolete and removed”.
| Wersja | A | AA | AAA | Razem | A + AA | Wytyczne |
|---|---|---|---|---|---|---|
| 2.0 | 25 | 13 | 23 | 61 | 38 | 12 |
| 2.1 | 30 | 20 | 28 | 78 | 50 | 13 |
| 2.2 | 31 | 24 | 31 | 86 | 55 | 13 |
Między 2.0 a 2.1 doszło 17 kryteriów (5 A, 7 AA, 5 AAA), żadne nie zniknęło i żadne nie zmieniło poziomu. Między 2.1 a 2.2 doszło 9 (2 A, 4 AA, 3 AAA), a 4.1.1 usunięto, też bez zmian poziomu. W aktualnym wydaniu WCAG 2.1 kryterium 4.1.1 wciąż ma poziom A, ale z uwagą, że dla treści w HTML lub XML należy je uznać za zawsze spełnione.
Załącznik do polskiej ustawy
Drugi skrypt czyta ustawę o dostępności cyfrowej z 2019 roku (Dz.U. 2019 poz. 848) z eli.gov.pl i porównuje kryteria z jej załącznika z 50 kryteriami A i AA WCAG 2.1. Załącznik wymienia 49 z nich (30 A, 19 AA), a poziomy się zgadzają. Brakuje tylko 1.2.4 Napisy rozszerzone (na żywo). To pasuje do art. 3 ust. 2 pkt 1, który wyłącza ze stosowania ustawy multimedia nadawane na żywo, choć sama ustawa nie podaje powodu pominięcia.
Skan axe-core dziesięciu stron
Puściłem axe-core w czystym Chromium na dziesięciu stronach cometweb.io: /, /pl, /pricing, /insight/accessibility, /tools/contrast, /pl/tools/a11y-checklist, /contact, /blog/accessibility-audit-wcag-eaa, /pl/blog/audyt-dostepnosci-wcag-eaa i /pl/glossary/wcag. To po jednej stronie z każdego szablonu, obie strony główne i dwie pary językowe. Okno miało 1280 × 800 z ograniczonym ruchem, a baner cookies został w stanie, w jakim widzi go nowy użytkownik. Skan ograniczyłem do reguł WCAG 2.1 A i AA, a reguły eksperymentalne były wyłączone, jak domyślnie.
Każde z 50 kryteriów A i AA WCAG 2.1 dostało potem jeden wynik, od najpoważniejszego:
| Wynik | Co znaczy | Kryteria |
|---|---|---|
| Naruszenie | reguła dla tego kryterium wykryła błąd na co najmniej jednej stronie | 1 |
| Do weryfikacji | reguła nie rozstrzygnęła na co najmniej jednej stronie | 3 |
| Reguły bez błędów | reguły zadziałały na prawdziwej treści i nic nie znalazły | 11 |
| Nie było czego sprawdzić | reguła istnieje, ale na stronach nie było wideo, audio, meta refresh ani migania | 4 |
| Tylko reguła eksperymentalna | kryterium pokrywa wyłącznie eksperymentalna reguła axe | 3 |
| Brak reguły | żadna reguła axe-core nie pokrywa tego kryterium | 28 |
Gdy axe wiąże regułę z kryterium, reguła sprawdza część tego kryterium. „Reguły bez błędów” znaczy więc, że zautomatyzowana część nic nie znalazła na tych dziesięciu stronach. Przykład: image-alt sprawdza, czy obraz ma tekst alternatywny, a czy ten tekst jest trafny, oceniasz już sam.
Co skan znalazł na mojej stronie
- Jedno naruszenie.
color-contrast(1.4.3) na/pricing: sześć elementów tekstu pomocniczego 12 px z kontrastem 4,49:1 (#7e7e7ena#151515) i 3,81:1 (#757575na#191919) przy wymaganym 4,5:1. To prawdziwy błąd mojej strony. - Do weryfikacji na każdej stronie.
color-contrastdla 88–209 elementów na stronę, razem 1460. Axe podał 1220 razy powód „tekst na tle z gradientem”, 100 razy „treść pseudoelementu”, 72 razy „tekst zbyt krótki do oceny”, 24 razy „nakładające się tła” i kilka innych. Do tegoaria-valid-attr-valueprzyaria-controlsw nawigacji, bo wskazany panel menu pojawia się dopiero po jego otwarciu, ilink-in-text-blockdla linku do polityki prywatności w zgodzie newslettera, który leży na gradiencie. - Do weryfikacji na pojedynczych stronach.
aria-hidden-focusw podglądzie demo na stronie głównej,aria-prohibited-attrna/insight/accessibilityith-has-data-cellsna/pricing.
Czego te dane nie pokażą
- Niczego, co musi sprawdzić człowiek: ścieżek klawiaturą, kolejności i widoczności focusu, czytników ekranu, powiększenia do 200%, dopasowania do 320 px CSS ani sensu tekstów alternatywnych i komunikatów błędów.
- Stanów po interakcji, czyli otwartych menu, wysłanych formularzy i okien dialogowych.
- Widoku mobilnego, innych silników przeglądarek i stron po zalogowaniu.
- Kryteriów, które są tylko w WCAG 2.2, i poziomu AAA.
- Zgodności z WCAG żadnej strony ani całego cometweb.io. Skan to pierwszy przegląd, a audyt wymaga kontroli ręcznych z tej listy.
Pliki
criteria-counts.jsonicriteria.csv: liczby i każde kryterium według wersji, poziomu i zasady, ze skrótem każdego dokumentu W3C, żeby kolejne uruchomienie pokazało, czy tekst się zmieniłannex-pl-2019.json: porównanie z załącznikiem do ustawyaxe-scan-results.json: każde naruszenie i element do weryfikacji z regułą, kryteriami, liczbą elementów i powodamiaxe-wcag21-coverage.json: wynik dla każdego z 50 kryteriówsources.json: dokumenty W3C, ustawa i inne źródła, z których korzystałemcount_criteria.py,count_annex_pl.py,run_axe_scan.mjs,build_charts.py: skrypty do liczenia kryteriów, porównania z ustawą, skanu i dwóch wykresów
Żeby to powtórzyć, uruchom python3 count_criteria.py i python3 count_annex_pl.py, które potrzebują tylko Pythona. Do skanu skopiuj criteria.csv i run_axe_scan.mjs do pustego katalogu, a potem uruchom npm i playwright@1.62.1 axe-core@4.13.0, npx playwright install chromium i node run_axe_scan.mjs. Liczby kryteriów wyjdą te same, dopóki dokumenty W3C się nie zmienią, a skan da inny wynik, kiedy zmienią się moje strony.