Зачем нужен цветовой контраст: от катаракты до яркого солнца
Доступность интерфейсов (accessibility, a11y) часто ошибочно воспринимают как заботу исключительно о тотально незрячих людях со скринридерами. Однако контрастность цветов напрямую затрагивает подавляющее большинство пользователей:
- Врождённые особенности цветового зрения. Около 8% мужчин и 0.5% женщин имеют ту или иную форму дальтонизма: дейтеранопию (нарушение восприятия зелёного спектра), протанопию (красного) или тританопию (синего). Если статус ошибки в форме показывается только бледно-красной рамкой, треть пользователей её просто не увидит.
- Возрастные изменения зрения. С возрастом естественный хрусталик глаза желтеет и мутнеет, зрачок пропускает меньше света, а контрастная чувствительность падает в 2–3 раза. Текст, который 20-летний дизайнер видит на откалиброванном мониторе iMac, для 55-летнего пользователя превращается в размытое серое пятно.
- Ситуативные ограничения. Использование смартфона на улице в солнечный полдень, просмотр дешёвого TN-монитора под углом или работа на ноутбуке с включённым режимом энергосбережения при яркости экрана 20%.
Стандарт WCAG 2.2 (Web Content Accessibility Guidelines, официальная рекомендация консорциума W3C с октября 2023 года) закрепляет строгие математические требования к контрасту, признанные международным стандартом ISO/IEC 40500 и законодательствами ЕС (European Accessibility Act) и США (ADA Title III).
Нормативы WCAG 2.2: уровни AA и AAA
В стандарте WCAG предусмотрено три уровня соответствия: A (минимальный), AA (отраслевой стандарт для всех коммерческих и государственных сайтов) и AAA (повышенный уровень для специализированных сервисов). Для визуального оформления критичны уровни AA и AAA:
| Элемент интерфейса | Размер / Определение | Уровень AA (обязательный) | Уровень AAA (повышенный) |
|---|---|---|---|
| Обычный текст | Меньше 24px (regular) или меньше 18.5px (bold) | 4.5 : 1 | 7.0 : 1 |
| Крупный текст | От 24px (regular) или от 18.5px (bold) | 3.0 : 1 | 4.5 : 1 |
| Нетекстовые элементы (SC 1.4.11) | Границы инпутов, чекбоксы, графики, иконки действий | 3.0 : 1 | — |
| Индикатор клавиатурного фокуса (SC 2.4.13) | Рамка вокруг активного интерактивного элемента | 3.0 : 1 | — |
Исключения: логотипы и товарные знаки, чисто декоративные фоновые иллюстрации и элементы, находящиеся в отключённом неактивном состоянии (атрибут disabled), освобождены от требований контрастности.
Математика контраста: относительная яркость и формула
Как именно вычисляется коэффициент контраста? Он основан на понятии относительной яркости (Relative Luminance, $L$), нормированной от 0.0 для абсолютно чёрного цвета до 1.0 для идеального белого.
Сначала значения цветовых каналов $sRGB$ пересчитываются из нелинейного гамма-пространства в линейную оптическую яркость. Для каждого канала ($R, G, B \in [0, 255]$):
C_srgb = C / 255
C_linear = (C_srgb <= 0.04045) ? (C_srgb / 12.92) : Math.pow((C_srgb + 0.055) / 1.055, 2.4) Затем вычисляется относительная яркость $L$ с физиологическими весовыми коэффициентами, отражающими чувствительность рецепторов человеческого глаза к разным длинам волн:
L = 0.2126 * R_linear + 0.7152 * G_linear + 0.0722 * B_linear
Зелёный цвет даёт свыше 71.5% воспринимаемой глазом яркости, красный — 21.3%, а синий — лишь 7.2%. Вот почему чистый синий текст #0000FF на чёрном фоне практически не читается, хотя имеет максимальное цифровое значение в канале цвета!
Итоговый коэффициент контраста между более светлым ($L_1$) и более тёмным ($L_2$) цветом вычисляется по формуле:
Contrast Ratio = (L1 + 0.05) / (L2 + 0.05)
Константа +0.05 введена W3C для учёта окружающего рассеянного света (ambient flare), отражающегося от стекла экрана при реальном освещении. Коэффициент варьируется от 1:1 (одинаковые цвета) до 21:1 (абсолютно белый против абсолютно чёрного).
WCAG 2 против APCA: почему старая формула ошибается
Формула WCAG 2 была разработана в 2008 году. За прошедшие годы исследователи зрительного восприятия выявили в ней ряд фундаментальных изъянов:
- Симметричность без учёта полярности. В формуле WCAG 2 отношение белого текста к чёрному фону математически равно отношению чёрного текста к белому фону (21:1). Но человеческий глаз устроен иначе: из-за светорассеяния на сетчатке белый текст на чёрном фоне кажется более жирным и размытым (эффект иррадиации).
- Игнорирование толщины и начертания (font-weight). Формула считает контраст одинаковым и для ультратонкого шрифта Thin 100, и для массивного жирного Black 900. В реальности тонкий серый текст 14px с контрастом 4.5:1 совершенно неразличим.
- Ложные срабатывания на средних тонах. Формула часто бракует превосходно читаемые сочетания (например, тёмно-оранжевый или синий на сером) и одобряет нечитаемые бледные цвета.
Новый алгоритм APCA (Accessible Perceptual Contrast Algorithm), разрабатываемый для будущего стандарта WCAG 3, рассчитывает показатель воспринимаемого контраста (обозначается как $L^c$). В APCA минимально необходимый балл $L^c$ напрямую привязан к матрице «размер шрифта × толщина штриха»: чем тоньше шрифт, тем более высокий физический контраст требуется.
Нетекстовый контраст и рамки фокуса (SC 1.4.11 и SC 2.4.13)
Одна из наиболее частых причин штрафов и судебных претензий по доступности — ошибки в интерактивных элементах управления:
Критерий SC 1.4.11 (Non-text Contrast)
Все визуальные границы, позволяющие понять форму и состояние компонента, обязаны иметь контраст не менее 3.0:1 относительно фона страницы.
Типичная ошибка дизайнеров: рисовать рамку текстового инпута модным светло-серым цветом #E2E8F0 на белом фоне #FFFFFF. Контраст этой границы составляет всего 1.3:1 — такой инпут буквально растворяется на экране для слабовидящих пользователей. Используйте для границ нейтральные оттенки с контрастом от 3:1 (например, #94A3B8 или темнее).
Критерий SC 2.4.13 (Focus Appearance в WCAG 2.2)
В стандарте WCAG 2.2 появился новый критерий уровня AA, регламентирующий видимость клавиатурного фокуса при навигации клавишей Tab:
- Индикатор фокуса должен иметь площадь не менее эквивалента полосы толщиной 2px по периметру элемента.
- Контраст рамки фокуса должен быть не менее 3.0:1 как относительно соседнего фона, так и относительно цвета элемента в расфокусированном состоянии.
/* КАТЕГОРИЧЕСКИ ЗАПРЕЩЕНО: */
button:focus { outline: none; }
/* ПРАВИЛЬНАЯ РЕАЛИЗАЦИЯ ПО WCAG 2.2: */
button:focus-visible {
outline: 2px solid #06b6d4;
outline-offset: 2px;
} Специфика контраста в темной и светлой теме
Создание тёмной темы — это не просто инверсия цветов. В тёмном окружении действуют специфические оптические законы:
- Отказ от чистого чёрного (#000000). Абсолютно чёрный фон с чисто белым текстом (
#FFFFFF) даёт максимальный контраст 21:1. В тёмной комнате это вызывает эффект гало (halation) — буквы начинают ослепительно «фонить» и двоиться, утомляя зрение пользователей с астигматизмом. Используйте тёмно-серые или сланцевые подложки:#0f172a,#121212,#1e293bс контрастом текста 12:1–15:1. - Высота слоёв (Elevation) вместо теней. В светлой теме глубина карточек и модальных окон задаётся тенями
box-shadow. На тёмном фоне тени не видны. По спецификации Material Design глубина создаётся постепенным высветлением поверхности: базовый фон#0b0f19, карточка#151c2e, выпадающее меню#1e293b. - Опасность перенасыщенных цветов. Яркие высоконасыщенные акценты (чистый ярко-синий
#0000FFили кислотно-зелёный), прекрасно выглядящие на белом, на тёмном фоне вызывают зрительную вибрацию. Для тёмных тем акцентные цвета десатурируют (снижают насыщенность на 15–25%) и слегка высветляют.
Построение доступной дизайн-системы: токены и правило 60-30-10
Чтобы веб-приложение всегда соответствовало стандарту без ручной проверки каждого пикселя, спроектируйте систему семантических токенов:
| Семантический токен | Светлая тема (Light) | Тёмная тема (Dark) | Гарантированный контраст |
|---|---|---|---|
--text-primary | #0f172a (Slate 900) | #f8fafc (Slate 50) | > 15 : 1 (с запасом под AAA) |
--text-muted | #475569 (Slate 600) | #94a3b8 (Slate 400) | > 4.6 : 1 (проходит AA) |
--border-control | #64748b (Slate 500) | #94a3b8 (Slate 400) | > 3.2 : 1 (проходит SC 1.4.11) |
--accent-focus | #0284c7 (Sky 600) | #38bdf8 (Sky 400) | > 3.5 : 1 (проходит SC 2.4.13) |
Критическое правило WCAG SC 1.4.1 (Use of Color): цвет никогда не должен быть единственным средством передачи информации, индикации действия или ошибки. Ошибку в поле формы необходимо сопровождать понятным текстовым сообщением и иконкой (⚠️), активную вкладку — подчеркиванием или меткой, а статус графика — контрастными паттернами штриховки в дополнение к цветовой заливке.
Частые вопросы
Какой минимальный контраст требуется для обычного текста по WCAG 2.2?
Для базового уровня соответствия Level AA минимальный коэффициент контраста составляет 4.5:1 для обычного текста (до 24px regular или до 18.5px bold). Для крупного текста (от 24px regular или от 18.5px bold) порог снижен до 3:1. Для наивысшего уровня AAA требования повышаются до 7:1 и 4.5:1 соответственно.
Нужно ли обеспечивать контраст 3:1 для границ полей ввода и кнопок?
Да. Критерий WCAG 2.2 SC 1.4.11 (Non-text Contrast) требует контраст не менее 3:1 между границей интерактивного элемента (инпута, чекбокса, вкладки) и окружающим фоном, если граница критична для распознавания формы компонента.
В чём принципиальное отличие алгоритма APCA от формулы WCAG 2?
Формула WCAG 2 статична и симметрична: она не учитывает толщину шрифта, его кегль и полярность (белое на черном читается иначе, чем черное на белом из-за рассеяния света в глазу). APCA (Accessible Perceptual Contrast Algorithm) рассчитывает воспринимаемый контраст (Lc) с учетом анатомии человеческого зрения и пространственной частоты.
Почему чистый черный (#000000) фон с белым (#FFFFFF) текстом утомляет глаза?
Контраст 21:1 в условиях низкой освещенности вызывает эффект гало (ореола вокруг букв) и зрительное утомление, особенно у пользователей с астигматизмом. В профессиональных дизайн-системах используют темно-серый фон (#121212 или #0f172a) с приглушенным белым текстом (#e2e8f0), обеспечивающим контраст ~15:1.
Каковы новые требования к рамкам фокуса (Focus Appearance) в WCAG 2.2?
Критерий SC 2.4.13 Level AA требует, чтобы индикатор фокуса имел площадь не менее периметра толщиной 2px вокруг компонента и контраст не менее 3:1 как по сравнению с состоянием без фокуса, так и относительно окружающего фона. Свойство outline: none без замены является прямым нарушением.