Kontrast kolorów WCAG: AA, AAA i APCA — kompletny przewodnik na 2026
Wdrażasz przycisk. Firmowy pomarańcz, biały tekst, na monitorze 4K wygląda ostro. Potem audyt dostępności wraca na czerwono: współczynnik kontrastu WCAG wynosi 1,97:1, dużo poniżej progu 4,5:1 dla tekstu podstawowego na poziomie AA. Przycisk, który wydawał się w porządku, jest nieczytelny dla mniej więcej 220 milionów osób z osłabionym widzeniem na świecie. Ten przewodnik prowadzi przez każdą liczbę potrzebną, by to naprawić: współczynniki WCAG 2, poziom AAA, nowy algorytm APCA Lc, osiem kategorii zaburzeń widzenia barw oraz działającą implementację w JavaScript, którą można wrzucić do builda.
Szybka ściąga: progi WCAG i APCA na jednym ekranie
| Standard | Tekst zwykły | Tekst duży | UI / ikony | Uwagi |
|---|---|---|---|---|
| WCAG AA | ≥ 4,5:1 | ≥ 3:1 | ≥ 3:1 | Bazowy próg prawny |
| WCAG AAA | ≥ 7:1 | ≥ 4,5:1 | ≥ 3:1 | Cel rozszerzony |
| APCA tekst | Lc 75+ | Lc 60+ | Lc 45+ (ikony) | Wersja robocza, percepcyjna |
„Tekst duży” oznacza ≥ 18pt regular lub ≥ 14pt bold (≈ 24px i ≈ 18,66px w CSS). „UI” obejmuje ramki formularzy, pierścienie focusa i każdy obiekt graficzny, który użytkownik musi dostrzec, by obsłużyć stronę. Loga i grafika czysto dekoracyjna są zwolnione z wymagań kontrastu.
Czym jest kontrast kolorów WCAG?
Kontrast WCAG to liczbowa miara od 1:1 (brak kontrastu) do 21:1 (maksimum), porównująca luminancję względną tekstu i jego tła. Web Content Accessibility Guidelines wymagają ≥ 4,5:1 (AA) dla tekstu podstawowego lub ≥ 7:1 (AAA) dla zgodności rozszerzonej.
Ten jeden wskaźnik steruje większością audytów dostępności na świecie. W3C opublikowało go w WCAG 2.0 w 2008 roku, dopracowało w 2.1 (2018) i 2.2 (2023), a dziś każdy poważny regulator się na niego powołuje. ADA w Stanach Zjednoczonych, European Accessibility Act (egzekwowany od czerwca 2025), Section 508 dla amerykańskich agencji federalnych oraz kanadyjska AODA: wszystkie te akty traktują WCAG 2.x AA jako de facto dolną granicę.
Dlaczego ma to znaczenie poza wymiarem prawnym? Około 220 milionów osób na świecie ma osłabione widzenie, ale nie jest niewidomych: czytają ekrany, lecz tylko wtedy, gdy kontrast czcionki i tła jest wystarczająco wysoki. Mniej więcej 8% mężczyzn i 0,5% kobiet ma zaburzenia widzenia barw. Starsi czytelnicy doświadczają zażółcenia soczewki i zmniejszenia źrenicy, co po 60. roku życia obniża postrzegany kontrast o 20–30%. Korzystanie ze smartfona na zewnątrz traci kolejne 20–40% przez odblaski. Strona, która na biurku daje 4,5:1, to próg, przy którym wszyscy ci użytkownicy nadal są w stanie ją przeczytać.
Najmocniej dotyczy to inżynierów front-endu wdrażających produkcyjne UI, projektantek dobierających firmowe palety, specjalistów od dostępności prowadzących audyty oraz zespołów compliance odpowiedzialnych za ryzyko prawne. Matematyka jest prosta; decyzje produktowe, które z niej wynikają, nie zawsze.
Współczynnik kontrastu WCAG 2.x: matematyka i progi
W3C definiuje kontrast w trzech krótkich krokach. Aby obliczyć kontrast WCAG: (1) przelicz każdy kolor z gamma-encoded sRGB na wartości w przestrzeni liniowej, (2) policz luminancję względną, używając stałych współczynników odzwierciedlających wrażliwość ludzkiego oka na czerwony, zielony i niebieski, a następnie (3) podziel obie luminancje z małym przesunięciem stałym, by obsłużyć wartości bliskie czarni.
Wzór na luminancję względną z WCAG 2.1 §1.4.3 wygląda tak:
L = 0.2126 × R_lin + 0.7152 × G_lin + 0.0722 × B_lin
R_lin, G_lin, B_lin to wartości kanałów w przestrzeni liniowej po odwróceniu krzywej gamma sRGB. Waga 0,7152 przy zielonym odzwierciedla silną wrażliwość oka na zieleń: zielony przy tej samej energii światła jest około 7× bardziej wizualnie głośny niż niebieski.
Wzór na współczynnik wygląda tak:
ratio = (L_lighter + 0.05) / (L_darker + 0.05)
Stała +0,05 zapobiega dzieleniu przez zero dla czystej czerni (L = 0) i daje maksimum (1 + 0,05) / (0 + 0,05) = 21:1 dla czystej bieli na czystej czerni. Minimum to 1:1, czyli kolory identyczne.
Poniżej pełna implementacja w mniej więcej trzydziestu liniach czystego JavaScript. Bez zależności, działa wszędzie:
// sRGB hex → kanał w przestrzeni liniowej
function srgbToLinear(channel8bit) {
const v = channel8bit / 255;
return v <= 0.04045 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
}
// "#RRGGBB" → luminancja względna [0, 1]
function relativeLuminance(hex) {
const h = hex.replace("#", "");
const r = parseInt(h.slice(0, 2), 16);
const g = parseInt(h.slice(2, 4), 16);
const b = parseInt(h.slice(4, 6), 16);
return (
0.2126 * srgbToLinear(r) +
0.7152 * srgbToLinear(g) +
0.0722 * srgbToLinear(b)
);
}
// Współczynnik kontrastu WCAG 2.x dla dwóch kolorów hex
function contrastRatio(hexA, hexB) {
const lA = relativeLuminance(hexA);
const lB = relativeLuminance(hexB);
const [lighter, darker] = lA > lB ? [lA, lB] : [lB, lA];
return (lighter + 0.05) / (darker + 0.05);
}
// Przykład: ciemny tekst slate na białym tle
console.log(contrastRatio("#475569", "#ffffff").toFixed(2));
// → "7.58" — komfortowo powyżej AA 4,5:1 i ledwie powyżej AAA 7:1
Wrzuć dwa kody hex do konwertera kolorów, a wrócą te same liczby, obok wartości APCA Lc, klasyfikacji gamutu oraz ośmiokanałowego podglądu CVD. Same progi są konkretne:
| Element | min. AA | min. AAA | Uwagi |
|---|---|---|---|
| Zwykły tekst | 4,5:1 | 7:1 | Poniżej 18pt regular / 14pt bold |
| Tekst duży | 3:1 | 4,5:1 | ≥ 18pt regular LUB ≥ 14pt bold |
| Elementy UI / ikony | 3:1 | — | WCAG 2.1 §1.4.11 dodane w 2018 |
| Loga i dekoracja | zwolnione | zwolnione | Brak wymogu kontrastu |
Przeliczenia jednostek CSS często mylą zespoły. 18pt = 24px przy domyślnej przeglądarce, 14pt = 18,66px. Czcionka 16px (współczesny domyślny rozmiar) jest poniżej progu „tekstu dużego”, więc podlega surowszej regule AA 4,5:1. Nagłówek 20px z font-weight: 700 kwalifikuje się jako duży i dostaje łagodniejsze 3:1.
Jeden niuans, który łapie zespoły z zaskoczenia: wyjątek WCAG dla „tekstu dużego” dotyczy czytelności dla użytkownika przy danej skali, a nie semantyki nagłówków. <h2> w 14px nie jest tekstem dużym i nadal potrzebuje 4,5:1. Akapit marketingowy w 24px jest tekstem dużym i dostaje próg 3:1. Reguła patrzy na rozmiar piksela i wagę po wyrenderowaniu, nigdy na nazwę znacznika. Audytorzy zaznaczą rozbieżności; źródłem prawdy jest CSS, nie semantyka HTML.
Stała +0,05 we wzorze na kontrast ma konkretne pochodzenie: reprezentuje człon flare, czyli światło otoczenia odbite od powierzchni ekranu, które podnosi pozorną luminancję czystej czerni do pewnego minimum. Bez niej piksel OLED renderujący prawdziwą czerń obok czystej bieli dawałby dzielenie przez zero. Z nią maksymalny osiągalny współczynnik to 21:1, czyli liczba, którą zobaczysz w każdym narzędziu dostępności. Nie istnieje fizyczny ekran, który po uwzględnieniu flare oddałby więcej niż 21:1, dlatego właśnie skala WCAG kończy się w tym miejscu.
AA czy AAA: który poziom obrać?
AA to prawna dolna granica, AAA to poziom aspiracyjny. Większość komercyjnych stron celuje w AA, bo AAA spycha firmowe kolory w stronę szarości, a tego marketing zwykle odmawia. Wybór jest kompromisem między zasięgiem użytkowników a ekspresją marki.
| Kontekst | Rekomendowany poziom | Dlaczego |
|---|---|---|
| Typowa strona komercyjna | AA | Próg zgodności z ADA / EAA; sądy powołują się na WCAG 2 AA |
| Administracja / usługi publiczne | AAA | Section 508 i analogiczne przepisy UE rekomendują AAA |
| Ochrona zdrowia / edukacja | AAA | Wśród odbiorców wyższy odsetek osób z potrzebami dostępności |
| Wewnętrzny dashboard | AA | Znana publiczność; kompromis na korzyść ROI |
| Strona lendingowa marketingu | AA + wyjątek brand | Firmowe kolory dozwolone w hero / CTA, body wciąż na AA |
Ukryty koszt AAA pojawia się przy pierwszej próbie przepuszczenia nasyconego firmowego pomarańczu na biel powyżej 7:1. Nie da się. Albo zaciemniasz pomarańcz, aż przestaje być rozpoznawalny jako kolor marki, albo akceptujesz AA i używasz pomarańczu na ciemnych tłach, gdzie z łatwością łapie AAA. Mnóstwo firm, także tych bardziej wyczulonych na dostępność, celuje w AA dla treści tekstowej, a AAA traktuje tylko dla krytycznych komunikatów, jak błędy formularzy czy klauzule prawne.
Regulatorzy nie czekali, aż AAA się rozpowszechni. Rozporządzenie ADA z 2024 dotyczące dostępności webu powołuje się na WCAG 2.1 AA. European Accessibility Act, egzekwowany od czerwca 2025, wymaga WCAG 2.1 AA we wszystkich objętych nim usługach cyfrowych. Section 508 w administracji federalnej USA przyjmuje WCAG 2.0 AA jako bazę (z AAA rekomendowanym, gdy to wykonalne). Kanadyjska AODA, ustawa o dostępności prowincji Ontario, wskazuje WCAG 2.0 AA. AA pozostaje minimum egzekwowanym przez przepisy; AAA jest osobnym celem jakościowym.
APCA: nowy algorytm percepcyjny
APCA (Advanced Perceptual Contrast Algorithm), zaprojektowany przez Andrew Somersa pod marką Myndex, jest algorytmem-kandydatem do WCAG 3. Zastępuje symetryczny współczynnik WCAG 2 wartością Lc z biegunowością, od -108 do +108, gdzie znak mówi, w którą stronę biegnie kontrast (ciemny tekst na jasnym tle vs jasny tekst na ciemnym), a wielkość odzwierciedla postrzegany kontrast na realnym wyświetlaczu emisyjnym.
APCA jest istotny, bo symetryczny wzór WCAG 2 pomija dwa realne efekty:
- Asymetria biegunowości. Jasny tekst na ciemnym tle czyta się inaczej niż ciemny tekst na jasnym, nawet przy tym samym współczynniku WCAG. WCAG 2 zwraca tę samą liczbę dla obu kierunków; APCA nie.
- Modelowanie wyświetlacza. Wzór WCAG 2 wyprowadzono z modeli luminancji papieru drukowanego. APCA dostrojono do wyświetlaczy sRGB w typowym oświetleniu biurowym, bliżej tego, co użytkownicy widzą naprawdę.
Kompromis: APCA jest bardziej złożony (ma wykładniki świadome biegunowości i korekty na wagę czcionki) i nie jest jeszcze standardem regulacyjnym. Analiza Adriana Roselli z kwietnia 2026 pozostaje najczystszym podsumowaniem statusu APCA: algorytm jest technicznie obiecujący, ale samo WCAG 3 wciąż siedzi we wczesnym drafcie ścieżki Silver, a APCA nie został jeszcze ratyfikowany jako oficjalny algorytm.
Progi APCA poziomu Bronze (praktyczna dolna granica, którą celuje większość zespołów) wyglądają tak:
| Zastosowanie | Rekomendowane Lc | Minimum Lc |
|---|---|---|
| Tekst podstawowy (16px, waga 400) | 90+ | 75 |
| Tekst duży (24px, waga 400) | 75+ | 60 |
| Elementy UI i ikony nietekstowe | 60+ | 45 |
| Tekst punktowy / placeholdery | 30+ | 30 |
Powód, dla którego APCA jest interesujący (i dla którego konwerter kolorów pokazuje obie metryki obok siebie), to przypadki, w których APCA nie zgadza się z WCAG 2:
#FFA500(pomarańczowy) na#FFFFFF: WCAG 2 zwraca 1,97:1, czyli jasną porażkę na AA. APCA się zgadza, dając mniej więcej Lc 38, też porażka. Oba algorytmy mówią nie, a mimo to większość projektantów, których obserwowałem, i tak wypuszcza to zestawienie, bo „wygląda nieźle”.#767676(średni szary) na#FFFFFF: WCAG 2 zwraca 4,54:1, ledwie ponad AA 4,5:1, technicznie zalicza. APCA daje tej parze około Lc 60, czyli poniżej progu Bronze 75 dla tekstu podstawowego. WCAG zalicza, APCA odrzuca. Doświadczenie użytkownika jest bliższe werdyktowi APCA: szary na bieli czyta się gorzej, niż sugeruje współczynnik.#3b82f6(Tailwind blue-500) na#000000: WCAG 2 zwraca 5,71:1, komfortowe AA. APCA daje około Lc 65, poniżej minimum Lc 75 dla tekstu podstawowego. Jasnoniebieski tekst na ciemnym tle, ukochany wzorzec trybu ciemnego, to kanoniczny przypadek „WCAG przepuszcza, APCA flaguje”.
Nie trzeba wybierać strony. Pragmatyczne podejście, do którego doszły zespoły produktowe: trzymaj WCAG 2 AA jako regulacyjną bazę, bo to do niej odnoszą się audyty zgodności, a APCA prowadź równolegle jako „czy to faktycznie się czyta?”, szczególnie przy projektach w trybie ciemnym i nasyconych kolorach marki. Konwerter kolorów pokazuje obie liczby w jednym wierszu, więc nie musisz przełączać kontekstu między checkerami.
Daltonizm i to, co poza kontrastem
Współczynnik kontrastu to dopiero połowa dostępności kolorystycznej. Około 8% mężczyzn i 0,5% kobiet widzi kolory inaczej niż podręcznikowy trichromat, a najczęstszy wariant, deuteranomalia, leży dokładnie w środku pary czerwony/zielony, której wszędzie używamy do oznaczeń sukces/błąd. WCAG 1.4.1 („Użycie koloru”) wprost zakazuje używania koloru jako jedynego nośnika informacji; to właśnie ta reguła ma temu zapobiegać.
Pełna taksonomia różnic widzenia barw dzieli się na trzy grupy: dichromatyzm (brak jednego rodzaju czopków), trichromatyzm anomalny (jeden rodzaj czopków przesunięty) oraz rzadkie monochromatyzmy.
| Typ | Nazwa potoczna | Kanał | Częstość (M / K) |
|---|---|---|---|
| Protanopia | Ślepota na czerwień | brak czopków L | 1,0% / 0,01% |
| Deuteranopia | Ślepota na zieleń | brak czopków M | 1,1% / 0,01% |
| Tritanopia | Ślepota na niebieski | brak czopków S | 0,003% / 0,003% |
| Protanomalia | Słabe widzenie czerwieni | przesunięte czopki L | 1,3% / 0,02% |
| Deuteranomalia | Słabe widzenie zieleni | przesunięte czopki M | 5,0% / 0,4% |
| Tritanomalia | Słabe widzenie niebieskiego | przesunięte czopki S | 0,01% / 0,01% |
| Achromatopsja | Brak kolorów | brak wszystkich czopków | 0,003% (bardzo rzadko) |
| Monochromatyzm czopkowy | Częściowa szarość | tylko jeden rodzaj czopków | 0,001% |
Sama deuteranomalia to 5% mężczyzn, jeden na dwudziestu. To ta grupa widzi czerwony wskaźnik błędu i zielony wskaźnik sukcesu jako niemal ten sam zgnitooliwkowy odcień. Naprawa nie polega na przeprojektowaniu systemu kolorów, tylko na dodaniu drugiego kanału. Czerwona ikona błędu w parze z kształtem „×” i słowem „Błąd” przetrwa każdy wariant z tabeli. Sam czerwony kropek nie przetrwa.
Symulacja CVD w kodzie korzysta z dwóch standardowych zestawów macierzy: Brettel–Viénot–Mollon (1997) dla dichromatyzmów oraz Machado–Oliveira–Fernandes (2009) dla trichromatyzmów anomalnych. Podejście Brettela rzutuje kolor wejściowy na płaszczyznę rozpiętą przez dwie zachowane odpowiedzi czopków; Machado parametryzuje przesunięcie czopka stopniem nasilenia. Oba da się zaimplementować jako filtry SVG lub macierze CSS. Konwerter kolorów dostarcza wszystkie osiem wariantów jako podgląd jednym kliknięciem, więc kolor marki możesz przeskanować po całym spektrum bez opuszczania strony.
Krótki filtr SVG (wrzuć na stronę i odwołaj się przez ID) da ci symulację protanopii w przeglądarce do szybkich testów:
<svg style="display: none">
<filter id="protanopia">
<feColorMatrix type="matrix" values="
0.567 0.433 0.000 0 0
0.558 0.442 0.000 0 0
0.000 0.242 0.758 0 0
0.000 0.000 0.000 1 0"/>
</filter>
</svg>
<style>
.preview-protanopia { filter: url(#protanopia); }
</style>
Zastosuj .preview-protanopia do wrappera strony, by zobaczyć, co widzi protanop. Powtórz z macierzami deuteranopii i tritanopii (ich współczynniki są opisane w pracy Brettela i dołączone do większości bibliotek symulujących CVD). Chrome DevTools w panelu Rendering ma te same symulatory wbudowane pod „Emulate vision deficiencies”; przydatne do szybkich sprawdzeń, mniej do robienia zrzutów ekranu w CI.
Głębsza zasada, ponad samą symulację: nigdy nie pozwól, by kolor był jedyną różnicą między dwoma stanami. Ikony powinny różnić się kształtem (× vs ✓), stany etykietą tekstową („Błąd” vs „Sukces”), kategorie wzorem (ciągły vs kreskowany). Kolor jest mnożnikiem na innych sygnałach, nie ich zamiennikiem.
Istnieje klasa awarii, których checkery kontrastu nie łapią, a symulatory CVD owszem. Segmenty wykresu kołowego rozróżniane wyłącznie barwą, legendy map kodujące państwa kolorem, statusowe pigułki oparte na gradiencie zielony/żółty/czerwony: wszystkie one mogą zaliczyć WCAG 2 względem tła, a jednocześnie być nieczytelne dla deuteranopa porównującego je ze sobą. Reguła brzmi: sprawdzaj czytelność między sąsiednimi kolorami w projekcie, nie tylko względem otaczającego płótna. Dwa segmenty slate-500 obok siebie przy tej samej jasności są nierozróżnialne, niezależnie od rotacji barwy. Dodaj między sąsiednimi obszarami skok luminancji, a wykres przetrwa każdy wariant CVD.
Achromatopsja i monochromatyzm czopkowy są rzadkie, ale warto je projektować świadomie, bo zlewają wszystkie rozróżnienia barwy. Osoba z achromatopsją odbiera tylko luminancję; UI zakodowane kolorami wygląda dla niej jak czarno-biała fotografia. Jeśli projekt broni się, gdy puścisz filter: grayscale(1) na całą stronę (spróbuj w DevTools), zdałeś najostrzejszą wersję reguły „kolor nie jest jedynym sygnałem”. Test zajmuje sekundę i często odsłania wady, które przy włączonym kolorze były niewidoczne.
Audyt palet Tailwind i Material
Większość pracy front-endowej korzysta z gotowej palety: Tailwind v4, Material 3, Radix albo shadcn. Pytanie o dostępność sprowadza się do „przy którym stopniu tej rampy tekst staje się czytelny?”, a odpowiedź jest bardziej zasadą kciuka, niż przyznają dokumenty.
Dla rampy slate w Tailwind v4 zestawionej z czystą bielą liczby WCAG i APCA układają się tak:
| Klasa Tailwind | Hex (przybliżony) | WCAG vs biel | AA body | AAA body | APCA Lc (przybl.) |
|---|---|---|---|---|---|
| slate-400 | #94a3b8 | 2,56:1 | ✗ | ✗ | ~38 ✗ |
| slate-500 | #64748b | 4,76:1 | ✓ | ✗ | ~60 ✗ body |
| slate-600 | #475569 | 7,58:1 | ✓ | ✓ | ~78 ✓ body |
| slate-700 | #334155 | 10,35:1 | ✓ | ✓ | ~90 ✓ body |
Wnioski praktyczne, które stąd wypadają:
- Tekst podstawowy wymaga slate-600 lub ciemniej. Slate-500 przepuszcza WCAG AA, ale oblewa próg APCA dla tekstu podstawowego: zgodny, ale niewygodny. Slate-600 to bezpieczna granica.
- Etykiety UI i tekst pomocniczy mogą używać slate-500. Elementy UI potrzebują tylko 3:1; 4,76:1 ze slate-500 jest komfortowe, a tekstowi towarzyszy zwykle dodatkowy kontekst wizualny.
- Placeholdery powinny używać slate-400 albo jaśniej. Tekst placeholdera jest zwolniony z WCAG 1.4.3 jako dekoracyjny tylko wtedy, gdy nad polem trzymasz widoczną etykietę. Wzorce „etykieta zamiast placeholdera” muszą trafić w próg tekstu podstawowego.
- Czysta czerń na slate-100 / slate-200 to marnowanie tuszu. Jesteś przy 17:1+; rozważ slate-700 albo slate-800 jako kolor tekstu, łagodniej w odbiorze, bez utraty czytelności.
Material 3 używa podobnej struktury palety tonalnej. Jego surface-container-high siedzi mniej więcej przy tone 92 (bardzo jasny), a on-surface przy tone 10 (prawie czarny). Kontrast między dowolnym on-surface a dowolnym tokenem surface-* w tej samej rodzinie jest spec-em Material zagwarantowany jako AA. Nie zestawiaj on-surface-variant (tone 30) z surface-container (tone 94) bez sprawdzenia; to realny błąd, który widziałem na produkcji.
Jeśli masz istniejącą paletę, która oblewa kontrast, OKLCH daje najczystszą ścieżkę naprawy. Zamiast po omacku majstrować przy kodach hex, przelicz kolor na OKLCH, przytrzymaj C (chroma) i H (hue), a zmniejszaj L (lightness), aż kontrast się zgodzi. Ponieważ kanał L w OKLCH jest genuinie percepcyjny, rozpoznawalność marki zostaje nienaruszona, a kontrast się zacieśnia. Konwerter HEX do OKLCH załatwia przeliczenie w jednym kroku; siostrzany wpis OKLCH wyjaśniony rozbiera matematykę głębiej.
Tryb ciemny zasługuje na osobny akapit. Symetryczny współczynnik WCAG 2 przepuszcza te same zestawienia w trybie jasnym i ciemnym z definicji. APCA, świadomy biegunowości, regularnie flaguje tekst podstawowy w trybie ciemnym jako trudniejszy do odczytu niż ta sama para hex w trybie jasnym. Jasny na ciemnym zawsze traci pewien postrzegany kontrast względem ciemnego na jasnym przy tym samym współczynniku liczbowym; to znany efekt adaptacji oka. Przed wydaniem produkcji puść APCA jeszcze raz na każdą parę z trybu ciemnego.
Checkery kontrastu i przepływy CI
Projektanci i inżynierowie mają swoich ulubieńców; praktyczne pytanie brzmi, którą kombinację narzędzi zszywasz w realnym przepływie. Tak wygląda pole w 2026 roku:
| Narzędzie | WCAG 2 | APCA | Symulacja CVD | Audyt palety |
|---|---|---|---|---|
| WebAIM Contrast Checker | ✓ | ✗ | ✗ | ✗ |
| Adobe Color | ✓ | ✗ | ✓ | ✓ |
| Stark (wtyczka Figma) | ✓ | ✓ | ✓ | ✓ |
| Polypane (przeglądarka) | ✓ | ✓ | ✓ | ✓ |
| Color Picker w Chrome DevTools | ✓ | ✓ (eksp.) | ✗ | ✗ |
| axe DevTools | ✓ | ✗ | ✗ | ✓ (poziom strony) |
| Konwerter kolorów Go Tools | ✓ | ✓ | ✓ (8 typów) | ✓ (Tints/Shades) |
Przepływ, który wytrzymuje realną presję produktową, wygląda tak:
- W Figmie projektantki puszczają Stark na każdą ramkę, by wcześnie wyłapać niezaliczone pary. Stark łapie oczywistych winowajców, zanim którykolwiek kod hex trafi do codebase’u.
- Przy przekazaniu hexa inżynierowie wklejają wartość do konwertera kolorów, by w jednym wierszu zobaczyć współczynnik WCAG + APCA Lc + klasyfikację gamutu + podgląd CVD. Jeśli para dotyczy trybu ciemnego albo nasyconej barwy marki, dwie metryki łapią przypadki „WCAG pass, APCA fail”, które Stark może przeoczyć.
- W czasie PR
axe-core/playwrightskanuje zbudowane strony pod kątem każdego naruszenia kontrastu na wyrenderowanym DOM, włącznie ze stanami dynamicznymi. To łapie pierścienie focusa, stany hover i wygląd elementów disabled, które statyczne pliki projektowe pomijają. - W QA zakładka Rendering w Chrome DevTools symuluje protanopię/deuteranopię/tritanopię do wyrywkowych sprawdzeń na krytycznych ścieżkach. Color Picker w DevTools pokazuje też współczynnik WCAG inline po najechaniu na element.
Pa11y, Lighthouse CI oraz @axe-core/playwright udostępniają asercje kontrastu w ramach szerszych audytów dostępności. Żaden z nich dziś nie sprawdza APCA; wszystkie sprawdzają WCAG 2. Realistyczny kompromis brzmi: „egzekwuj WCAG 2 AA w CI, APCA Lc puść ręcznie na zdrowy rozsądek dla kolorów marki i trybu ciemnego”.
Wzorzec wart podpatrzenia od większych zespołów design-system: wpinaj sprawdzenie kontrastu w krok walidacji tokenów, nie tylko w QA na poziomie strony. Jeśli tokeny projektowe kompilują się z pliku źródłowego (JSON, YAML albo modułu TypeScript), dodaj skrypt, który wylicza każde zestawienie --text-* × --surface-* dozwolone przez system i sprawdza minimalny współczynnik WCAG. Skrypt biegnie w milisekundach, łapie regresje, gdy ktoś podkręci wartość tokenu, i produkuje macierz kontrastu, która zarazem służy zespołowi projektowemu za dokumentację. Sprawdzenie jest niezależne od jakiejkolwiek wyrenderowanej strony; działa wyłącznie na tokenach, więc łapie awarię, zanim trafi do UI.
Do konwersji ad hoc podczas tego przepływu (między hex, RGB, HSL i OKLCH w trakcie debugowania) masz konwerter HEX do RGB, konwerter HEX do HSL, konwerter HEX do OKLCH oraz konwerter RGB do HEX, które obsłużą podróże w obie strony do dowolnego formatu, jakiego wymaga toolchain.
Częste błędy i jak je naprawić
Po latach audytów dostępności wraca tych samych sześć potknięć. Każde ma porządną naprawę:
-
Placeholder w jasnoszarym.
#999999na bieli daje 2,85:1, czyli oblewa AA. Albo pogłęb do#666666(5,74:1, zalicza AA), albo, lepiej, zastąp wzorzec „placeholder zamiast etykiety” trwale widoczną etykietą nad polem. Placeholdery nie powinny nieść informacji. -
Firmowy pomarańczowy przycisk z białym tekstem.
#FFA500na bieli daje 1,97:1, czyli oblewa AA z dużym zapasem. Naprawa, która zachowuje markę, polega na odwróceniu kierunku kontrastu: ciemny tekst (np.#451a03) na pomarańczowym tle albo zachowanie białego tekstu i ściemnienie przycisku do nasyconego brązowopomarańczowego. Zweryfikuj w konwerterze kolorów, zanim wydasz. -
Jasnoniebieski link w trybie ciemnym.
#3b82f6na#000000daje 5,71:1 (WCAG AA zalicza), ale APCA Lc ~65, poniżej progu Lc 75 dla tekstu podstawowego. Sięgnij po OKLCH i podbij L z ≈ 0,63 do 0,75, trzymając C i H bez ruchu; wylądujesz blisko#7aa5f8z komfortowym APCA Lc 80+ i tą samą barwą. -
Tekst disabled w
#CCCCCC. Daje 1,61:1 na bieli. WCAG 1.4.3 zwalnia z reguły kontrastu czysto dekoracyjny tekst, ale kontrolki UI w stanie disabled nie są dekoracyjne; komunikują „to jest obecnie niedostępne”. Sparuj wygaszony kolor z sygnałem niekolorowym (przekreślenie, ikona kłódki, tooltip „Wyłączone”), żeby osoba z CVD lub z osłabionym wzrokiem wciąż rozumiała stan. -
Ikony statusu różniące się tylko barwą. Czerwone
×i zielone✓jest w porządku, bo kształt już je rozróżnia. Czerwona kropka kontra zielona kropka — już nie. Używaj kształtu i koloru razem; podgląd CVD w konwerterze kolorów demaskuje przypadek awarii w sekundę. -
Tekst nad tłem z gradientem. Gradient biegnący od
#3b82f6do#a78bfazaliczy kontrast z białym tekstem w środku, a oblewa przy lawendowym końcu. Naprawa polega na egzekwowaniu kontrastu względem najgorszego punktu gradientu albo na nałożeniu półprzezroczystej ciemnej zasłony, by efektywna luminancja tła zawsze siedziała poniżej znanego progu.
Każda z tych napraw zajmuje kilka minut przy projektowaniu. Powtórny cykl audytu, gdy je przegapisz, ciągnie się tygodniami.
FAQ
Czym jest współczynnik kontrastu WCAG AA?
WCAG AA wymaga ≥ 4,5:1 między tekstem podstawowym a tłem albo ≥ 3:1 dla tekstu dużego (≥ 18pt regular lub ≥ 14pt bold) i komponentów UI w rodzaju ramek formularzy. AA to prawna baza pod ADA, EAA i Section 508; większość komercyjnych stron celuje w AA, bo pokrywa wymogi regulacyjne bez spychania kolorów marki w stronę szarości.
Jaki kontrast jest potrzebny do AAA?
WCAG AAA wymaga ≥ 7:1 dla zwykłego tekstu podstawowego i ≥ 4,5:1 dla tekstu dużego. AAA jest rekomendowane dla medycyny, edukacji i administracji, gdzie odbiorcy częściej mają zwiększone potrzeby dostępności. Firmowe kolory często trzeba spłaszczać w stronę bliską szarości, by zdały AAA; dlatego wiele produktów komercyjnych zatrzymuje się na AA.
Czym jest APCA i czy to WCAG 3.0?
APCA (Advanced Perceptual Contrast Algorithm), zaprojektowany przez Andrew Somersa / Myndex, jest algorytmem-kandydatem w projekcie WCAG 3 Silver. Używa wyników Lc świadomych biegunowości w zakresie od -108 do +108 zamiast symetrycznych współczynników. W 2026 roku WCAG 3 wciąż siedzi we wczesnym drafcie, a APCA nie został formalnie ratyfikowany; WCAG 2.1 / 2.2 AA pozostaje regulacyjnym standardem, w który dziś trzeba trafiać.
Czy tryb ciemny pomaga w dostępności kontrastu?
Czasem, ale nie automatycznie. Symetryczny współczynnik WCAG 2 przepuszcza te same zestawienia w trybie jasnym i ciemnym, lecz APCA (świadomy biegunowości) często flaguje tekst podstawowy w trybie ciemnym jako trudniejszy do odczytu niż ta sama para hex w trybie jasnym. Zawsze testuj tryb ciemny zarówno przez WCAG, jak i APCA przed wydaniem; jasny na ciemnym traci postrzegany kontrast w sposób, którego symetryczny współczynnik nie zobaczy.
Dlaczego mój kolor marki oblewa WCAG AA?
Nasycone kolory o średniej luminancji (większość pomarańczy, żółcie, limonkowe zielenie, jasne błękity) mają luminancję względną zbyt bliską bieli, by zaliczyć 4,5:1. Naprawa: zachowaj barwę marki na akcenty i duże nagłówki, ale sparuj tekst podstawowy z ciemniejszym tonem z tej samej rodziny barw. Użyj OKLCH, by obniżyć kanał L bez zmiany barwy; konwerter kolorów znajduje najbliższy zaliczający odcień w jednym kroku.
Czy współczynniki WCAG 2 i wyniki APCA są wymienne?
Nie. WCAG 2 zwraca symetryczny współczynnik (1–21); APCA zwraca wynik Lc z biegunowością (-108 do +108). Zależność jest nieliniowa: para z 4,5:1 w WCAG może dać Lc 60 albo Lc 75 w APCA w zależności od tego, który kolor jest na górze. Traktuj je jako dwa niezależne sprawdzenia, nie jako tłumaczenia siebie nawzajem.
Czy można używać kontrastu kolorów dla małych ikon UI?
Tak, z zastrzeżeniami. WCAG 2.1 §1.4.11 wymaga ≥ 3:1 dla komponentów UI i obiektów graficznych. Dla ikon dekoracyjnych w parze z widoczną etykietą tekstową wymogi kontrastu się luzują, bo etykieta niesie znaczenie. Dla ikon samodzielnych (np. lupa wyszukiwania bez etykiety) egzekwuj pełne 3:1 względem otaczającego tła.
Jak testować daltonizm bez symulacji?
W Chrome DevTools → Rendering → „Emulate vision deficiencies” są symulacje protanopii, deuteranopii, tritanopii i achromatopsji. Połącz to z 8-typowym podglądem CVD w konwerterze kolorów dla wariantów trichromatyzmu anomalnego (deuteranomalia jest najczęstsza, 5% mężczyzn). Do raportów audytowych rób zrzuty pod każdą symulacją, by recenzenci widzieli tryby awarii inline.
Podsumowanie
Pięć rzeczy, które warto zapamiętać:
- AA 4,5:1 to prawna baza. Trafiaj w nią dla całego tekstu podstawowego albo licz się z hałasem audytowym.
- AAA 7:1 jest dla medycyny, edukacji i administracji. Większość marek komercyjnych z założenia zatrzymuje się na AA.
- APCA Lc to sanity check realnej czytelności. Puszczaj go równolegle z WCAG 2, zwłaszcza dla trybu ciemnego i nasyconych kolorów marki.
- Kolor nigdy nie jest jedynym sygnałem. Każdy bodziec kolorystyczny sparuj z kształtem, tekstem lub wzorem; sama deuteranomalia to 5% męskich użytkowników.
- L w OKLCH to właściwa gałka. Gdy kolor oblewa kontrast, obniżaj L (nie S, nie B), żeby naprawić bez dryfu barwy.
Wrzuć dowolne dwa kody hex do konwertera kolorów, by zobaczyć współczynnik WCAG, APCA Lc, klasyfikację gamutu i 8-typowy podgląd CVD obok siebie. Ten jeden widok zastępuje sześć osobnych narzędzi i jest najszybszą drogą do domknięcia audytów, które opisuje ten przewodnik.