Контрастные интерфейсы и читаемость
1) Зачем контраст
Контраст определяет, насколько быстро и безошибочно пользователь распознает текст, иконки и состояния. Высокий контраст:- снижает когнитивную нагрузку и утомляемость,
- улучшает скорость сканирования интерфейса,
- повышает доступность для людей с нарушениями зрения и цветового восприятия,
- уменьшает количество ошибок во взаимосвязанных сценариях (платежи, формы, подтверждения).
2) Базовые понятия и формулы
2.1 Контраст по WCAG
Контраст — это отношение яркостей переднего плана и фона:- Contrast = (L1 + 0.05) / (L2 + 0.05), где `L1 ≥ L2`, `L` — относительная яркость (0..1).
2.2 Относительная яркость (sRGB)
1. Приведите компоненты R, G, B в диапазон 0..1.
2. Линеаризация sRGB:- если `c ≤ 0.04045`, то `c_lin = c / 12.92`
- иначе `c_lin = ((c + 0.055) / 1.055) ^ 2.4`
3. Яркость: `L = 0.2126 R_lin + 0.7152 G_lin + 0.0722 B_lin`
2.3 Цветовые представления
HSL/HSV — удобны для ручной настройки, но не равномерны перцептуально.
Lab/LCH/OKLCH — ближе к восприятию человека; OKLCH удобен для систематической вариации светлоты/насыщенности при сохранении читаемости.
3) Нормы и цели (WCAG 2.2)
Текст ≥ 14 pt bold или ≥ 18 pt (обычный): контраст минимум 3:1 (AA).
Остальной текст: контраст минимум 4.5:1 (AA).
AAA (повышенная читаемость): 7:1 для обычного текста; 4.5:1 для крупного.
Иконография и важные нефотографические элементы (границы полей ввода, чекбоксы, переключатели, индикаторы ошибок): ориентир 3:1 с фоном.
Состояния (hover/focus/pressed/disabled) должны иметь различимость не ниже 3:1 между состояниями или с фоном, плюс явные нефотографические индикаторы (подчеркивание ссылок, тени/рамки, изменение толщины).
4) Дизайн-система: токены контраста
Рекомендуем в дизайн-системе фиксировать контраст как свойство токенов.
Пример уровней:- `fg/primary` ↔ `bg/base` ≥ 7:1 (AAA для критичного текста)
- `fg/secondary` ↔ `bg/base` ≥ 4.5:1
- `fg/muted` ↔ `bg/subtle` ≥ 3:1 (служебный текст)
- `border/default` ↔ `bg/base` ≥ 3:1 (границы полей, карточек)
- `interactive/default` ↔ `bg/base` ≥ 4.5:1 (ссылки/кнопки)
- `interactive/disabled` не должен имитировать активные состояния; используйте снижение контраста и курсор/ARIA-атрибуты.
- базовая светлота темы (L), затем отклонения `ΔL` для слоев/поверхностей (`bg/subtle`, `bg/elevated`),
- фиксируйте минимальные контрастные пары в тестах.
5) Светлая и темная темы
Светлая тема: текст почти черный (не чистый #000, а теплый/холодный оттенок), фон от белого до слегка тонированного, чтобы уменьшить «сверкание».
Темная тема: избегайте чистого #000 фона — глубокий графит/уголь с L≈0.12–0.16 снижает засветы; белый текст смягчайте до L≈0.9.
Сохраняйте одинаковые контрастные цели в обеих темах; не допускайте, чтобы цветовые акценты теряли читаемость на темном фоне (часто нужен сдвиг `ΔL` и снижение насыщенности).
6) Текст на изображениях и видео
Используйте оверлеи (градиент/полупрозрачный слой 40–60%) или плашки под текстом.
Закрепляйте минимум 4.5:1 между текстом и локальным фоном плашки.
Для динамического видео — адаптивный фон/оверлей по анализу яркости кадра (сэмплинг центральной/подложной области).
7) Состояния и интерактивность
Ссылки должны быть различимы не только цветом: подчеркивание по умолчанию или подчеркивание на hover/focus + контраст ≥ 3:1 с обычным текстом.
Кнопки: текст и иконка ≥ 4.5:1 к заливке; заливка ≥ 3:1 к окружению.
Ошибки/успех/предупреждения: не полагайтесь на цвет; добавляйте иконки/текстовые подсказки; обеспечивайте контраст текста минимум 4.5:1.
8) Люди с нарушениями цветового восприятия
Поддерживайте различимость в режимах:- Deuteranopia/Protanopia (красно-зеленая зона): избегайте комбинаций «красный vs зеленый» без дополнительных признаков.
- Tritanopia: сине-желтые пары проверять отдельно.
- Делайте формы и графики понятными: текстовые метки, разные типы штрихов/маркеров, узоры заливки, подписи к сегментам.
9) Типографика и фон
Кегль основного текста: 14–16 px минимум (web), 16–18 px для контентных зон.
Межстрочный интервал 1.4–1.6 улучшает читаемость на фоне с высоким контрастом.
Избегайте тонких начертаний на недостаточном контрасте.
Текст на цветных фонах: уменьшайте насыщенность фона и/или увеличивайте светлоту, чтобы выйти на целевое отношение.
10) Диаграммы, таблицы, графики
Линии/столбцы ≥ 3:1 к сетке/фону.
Подписи осей и легенды ≥ 4.5:1.
Используйте различимые формы/паттерны помимо цвета.
11) Динамический/адаптивный контраст
Auto contrast: вычисляйте контрастный цвет текста к выбранной заливке (напр., через OKLCH: подбор `L` для достижения 4.5:1).
Системные настройки: уважайте `prefers-contrast`, `forced-colors`, high-contrast режимы ОС.
Персонализация: настройка «Высокий контраст» в приложении (усиление `ΔL`, замена брендовых акцентов на более нейтральные с сохранением фирменности через форму/иконки).
12) Процессы и автоматизация контроля
12.1 Для дизайнеров
Проверяйте контраст на макетах (в обеих темах и на ключевых фонах).
Вводите «контрастные слоты» в компонентах (title/primary/secondary/hint).
Документируйте допустимые фоновые контексты для каждого компонента.
12.2 Для разработчиков
Юнит-хелперы: функция расчета контраста и ассерты в тестах для токен-пар.
Визуальные снапшоты с проверкой контрастных метрик (скрин-рендер + вычисление L1/L2 по сэмплам).
Линтеры стилей: запрет «сырого» цвета, только через токены.
12.3 В CI/CD
Проверка всех пар `fg/bg` в темах и состояниях.
Отчет по нарушениям с указанием компонента, варианта, темы и фактического значения (например, 3.9:1 при требуемых 4.5:1).
13) Специфика iGaming (опционально)
Яркие промо-баннеры и карточки турниров часто «съедают» текст. Требуется плашка/оверлей и ограничение насыщенности фона.
Системные элементы ответственных уведомлений (18+, лимиты, риски) — AAA по контрасту.
В таблицах лидеров/коэффициентах: числа и знаки «+/-» ≥ 4.5:1, подсветка выигрыша — не только цветом (иконки/метки).
14) Антипаттерны
Полагаться только на цвет для различимости состояния.
Тонкие серые шрифты на цветном фоне без расчета контраста.
«Темно-на-темном» в Dark Mode, «ярко-на-ярком» в промо-зонах.
Текст на фоне с деталями/шумом без плашки.
15) Чек-лист для ревью
Базовый текст
- ≥ 4.5:1 (обычный), ≥ 3:1 (крупный/жирный).
Ссылки/кнопки
- Текст кнопки ≥ 4.5:1 к заливке.
- Различимость состояний ≥ 3:1 или явные индикаторы.
Иконки/границы
- ≥ 3:1 к фону.
Темная/светлая темы
- Те же цели контраста достигнуты.
Медиа-фоны
- Оверлей/плашка, коэффициент выдержан.
Доступность
- Есть нефотографические признаки помимо цвета.
Автоматизация
- Тесты контраста в CI/CD по токенам и компонентам.
16) Внедрение токенов (пример нотации)
color.bg.base = oklch(0.95 0.02 260)
color.fg.primary = oklch(0.18 0.04 260) # ≈7:1 color.fg.secondary = oklch(0.30 0.03 260) # ≥4.5:1 color.border = oklch(0.40 0.03 260) # ≥3:1 color.accent = oklch(0.65 0.12 230) # проверить на обоих фонах
Примечание: значения примерные; финальные подбираются по расчету контраста в конкретной теме.
17) Документация для команды
В гайдлайнах укажите: цели контраста, примеры верных/ошибочных пар, матрицу `fg×bg` для ключевых компонентов, правила для медиа-фонов, и как включать режим «Высокий контраст».
Держите живую страницу «Исключения и причины» (например, разрешен 3.8:1 в узком кейсе крупного дисплейного заголовка).
Краткое резюме
Контраст — измеряемый параметр, а не вкусовой. Задайте цели (AA/AAA), управляйте ими через токены (лучше в OKLCH), проверяйте автоматически в CI и визуально в макетах, учитывайте темную/светлую темы и людей с нарушениями цветового зрения. Это гарантирует читаемость, снижает ошибки и повышает конверсию.