Модуль 7 · урок 7 з 10
Контраст і колір
«Color contrast compliance» — єдина вимога доступності, яку можна перевірити числом. Формула проста, поріг відомий, інструмент є в кожному браузері. Тому це і найшвидший спосіб закрити пункт із таблиці, і найлегший спосіб його провалити.
Пороги
| Що | Мінімум (AA) | Підвищений (AAA) |
|---|---|---|
| Звичайний текст | 4.5 : 1 | 7 : 1 |
| Великий текст (від 18pt або 14pt жирний) | 3 : 1 | 4.5 : 1 |
| Межі полів, іконки, індикатор фокуса | 3 : 1 | — |
| Декоративні елементи | без вимог | — |
Практичний орієнтир: 4.5:1 для тексту, 3:1 для всього, на що треба дивитись. Цього достатньо, щоб пройти перевірку й не мучити людей із слабким зором.
Як рахується
// 1. канал sRGB у лінійне значення
function channel(v) { // v від 0 до 1
return v <= 0.03928 ? v / 12.92 : Math.pow((v + 0.055) / 1.055, 2.4);
}
// 2. відносна яскравість кольору
function luminance([r, g, b]) {
return 0.2126 * channel(r / 255)
+ 0.7152 * channel(g / 255)
+ 0.0722 * channel(b / 255);
}
// 3. співвідношення: світліший до темнішого
function contrast(a, b) {
const l1 = Math.max(luminance(a), luminance(b));
const l2 = Math.min(luminance(a), luminance(b));
return (l1 + 0.05) / (l2 + 0.05);
}
Зелений входить із вагою 0.7152, а синій — лише 0.0722. Це не довільні числа: людське око значно чутливіше до зеленого. Практичний наслідок — синій текст на чорному майже завжди провалює перевірку, навіть коли візуально здається яскравим. А жовтий на білому провалює ще частіше, хоч і здається кричущим.
Найчастіші місця провалу
- Основний текст на фоні сторінки.
- Білий текст на насиченій кнопці.
- Заголовки.
- Приглушений текст — підказки, підписи, «вторинний» сірий.
- Плейсхолдер у полі вводу — майже завжди надто світлий.
- Вимкнені елементи — формально виняток, але користувач має розуміти, що там написано.
- Статус-бейджі — кольоровий текст на кольоровому фоні.
- Індикатор фокуса — часто робиться ледь помітним.
- Темна тема — світлий текст на темному поводиться інакше, ніж очікуєш.
Як перевіряти
// 1. DevTools: навести на колір у панелі Styles — контраст показується одразу
// 2. Lighthouse → Accessibility: знайде всі проблемні пари на сторінці
// 3. axe DevTools: детальніше, з поясненням кожної
// 4. Свій тест у консолі — для токенів теми
// швидка перевірка всіх пар токенів
const pairs = [
['--color-ink', '--color-bg'],
['--color-ink-3', '--color-surface'], // ← ось тут зазвичай і провал
['--color-accent', '--color-bg'],
];
Пара кольорів, яка проходить у світлій темі, може провалитись у темній — і навпаки. Оскільки в модулі 1 ти зробив теми на токенах, перевірити треба обидва набори значень. Найчастіше страждає приглушений текст: у темній темі його роблять надто темним, щоб «не різав очі».
Колір ніколи не єдиний носій змісту
<!-- ❌ різниця лише в кольорі -->
<span class="dot dot--red"></span>
<span class="dot dot--green"></span>
<!-- ✅ колір, форма й текст -->
<span class="badge badge--blocked"><span aria-hidden="true">⏸</span> Заблоковано</span>
<span class="badge badge--done"><span aria-hidden="true">✓</span> Готово</span>
Приблизно кожен дванадцятий чоловік не розрізняє червоне й зелене. Для нього дві крапки — однакові сірі кружечки. Текст поруч вирішує проблему повністю й нікому не заважає.