Цветовая доступность: контраст, дальтонизм и соответствие WCAG

Утилиты

Цветовая доступность: не только «красиво»

Около 8% мужчин и 0,5% женщин в мире имеют нарушения цветового зрения — 1 из 12 пользователей не может нормально различать определённые цвета.

Тип нарушения цветового зрения Распространённость Трудноразличимые цвета
Протанопия (красная слепота) 1% Красный-зелёный
Дейтеранопия (зелёная слепота) 5% Красный-зелёный
Тританопия (синяя слепота) 0,003% Синий-жёлтый
Ахроматопсия (полная цветовая слепота) Крайне редко Все

I. Стандарты контрастности WCAG

Уровни соответствия

Уровень Обычный текст Крупный текст Компоненты UI
AA ≥ 4,5:1 ≥ 3:1 ≥ 3:1
AAA ≥ 7:1 ≥ 4,5:1 —

Определение крупного текста: ≥ 18pt (24px) или ≥ 14pt жирный (18,66px bold).

Расчёт контрастности

Контрастность = (L1 + 0,05) / (L2 + 0,05)

L1 = Относительная яркость более светлого цвета
L2 = Относительная яркость более тёмного цвета

Относительная яркость L:
  Для sRGB где sRGB ≤ 0,03928: L = sRGB / 12,92
  Для sRGB где sRGB > 0,03928: L = ((sRGB + 0,055) / 1,055)^2,4

  sRGB = R/255, G/255, B/255 (рассчитывается для каждого канала)

Контрастность распространённых комбинаций

Передний план Фон Контрастность AA обычный текст AA крупный текст
#000000 #FFFFFF 21:1 ✅ ✅
#333333 #FFFFFF 12,6:1 ✅ ✅
#666666 #FFFFFF 5,7:1 ✅ ✅
#767676 #FFFFFF 4,5:1 ✅ (точно) ✅
#999999 #FFFFFF 2,8:1 ❌ ❌
#FF0000 #FFFFFF 3,99:1 ❌ ✅
#0000FF #FFFFFF 8,59:1 ✅ ✅

II. Проверка контрастности с помощью ToolsKu

Шаги использования

  1. Откройте инструмент цветового контраста
  2. Введите цвет переднего плана и фона (поддерживает HEX, RGB, HSL)
  3. Просмотрите результаты:
    • Коэффициент контрастности
    • Статус соответствия WCAG AA / AAA
    • Отдельная оценка для обычного текста / крупного текста
  4. Корректируйте цвета до соответствия

III. Моделирование дальтонизма

Моделирование с помощью CSS filter

/* Протанопия */
.protanopia { filter: url('#protanopia'); }

/* Дейтеранопия */
.deuteranopia { filter: url('#deuteranopia'); }

/* Тританопия */
.tritanopia { filter: url('#tritanopia'); }

Матрица SVG-фильтра

<svg style="display:none">
  <!-- Матрица моделирования протанопии -->
  <filter id="protanopia">
    <feColorMatrix type="matrix" values="
      0.567  0.433  0      0  0
      0.558  0.442  0      0  0
      0      0.242  0.758  0  0
      0      0      0      1  0
    "/>
  </filter>

  <!-- Матрица моделирования дейтеранопии -->
  <filter id="deuteranopia">
    <feColorMatrix type="matrix" values="
      0.625  0.375  0      0  0
      0.7    0.3    0      0  0
      0      0.3    0.7    0  0
      0      0      0      1  0
    "/>
  </filter>
</svg>

IV. Стратегии адаптации для дальтоников

Стратегия 1: Не полагаться только на цвет для передачи информации

<!-- Неправильно: различение состояний только по цвету -->
<span class="status-error" style="color: red">Ошибка</span>
<span class="status-success" style="color: green">Успешно</span>

<!-- Правильно: цвет + значок -->
<span class="status-error" style="color: red">
  <svg>✕</svg> Ошибка
</span>
<span class="status-success" style="color: green">
  <svg>✓</svg> Успешно
</span>

Стратегия 2: Использовать дружественные для дальтоников цветовые комбинации

Комбинация, которой следует избегать Альтернативная комбинация
Красный + Зелёный Красный + Синий, или Оранжевый + Синий
Светло-красный + Светло-зелёный Тёмно-красный + Светло-зелёный
Зелёный успех + Красный ошибка Синий информация + Оранжевый предупреждение

Палитра Wong, дружественная для дальтоников

#000000 Чёрный
#E69F00 Оранжевый
#56B4E9 Голубой
#009E73 Бирюзово-зелёный
#F0E442 Жёлтый
#0072B2 Синий
#D55E00 Киноварь
#CC79A7 Розово-фиолетовый

Эта палитра различима при всех типах нарушений цветового зрения.

Стратегия 3: Использовать текстуры/узоры в диаграммах

/* Разные ряды данных используют разные текстуры */
.series-a { background-image: url('stripes.svg'); }
.series-b { background-image: url('dots.svg'); }
.series-c { background-image: url('crosshatch.svg'); }

V. Доступность в тёмном режиме

Ловушки контрастности в тёмном режиме

Ловушка Описание Решение
Чисто чёрный фон с чисто белым текстом Контрастность 21:1, но вызывает напряжение глаз Использовать тёмно-серый фон (#1a1a2e)
Снижение насыщенности Высокая насыщенность в тёмном режиме режет глаза Умеренно снизить насыщенность
Тени не видны Тени исчезают на тёмном фоне Использовать рамки или разницу яркости
Недостаточный контраст изображений Детали изображений теряются в тёмном режиме Корректировать с помощью CSS filter

Рекомендации по цветам для тёмного режима

:root {
  /* Светлый режим */
  --bg: #ffffff;
  --fg: #1a1a2e;
  --muted: #6b7280;
  --accent: #3b82f6;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #1a1a2e;
    --fg: #e0e0e0;
    --muted: #9ca3af;
    --accent: #60a5fa; /* Более светлый синий, сохраняет контрастность */
  }
}

VI. Проверка доступности на уровне компонентов

Сообщения об ошибках в формах

<!-- Неправильно: только красная рамка как индикация -->
<input style="border: 1px solid red" />

<!-- Правильно: рамка + текст + aria -->
<input
  style="border: 1px solid red"
  aria-invalid="true"
  aria-describedby="error-msg"
/>
<span id="error-msg" role="alert" style="color: #dc2626">
  Пожалуйста, введите корректный адрес электронной почты
</span>

Контраст между ссылками и окружающим текстом

Ссылки нуждаются не только в достаточном контрасте с фоном, но и в визуальном отличии от окружающего текста:

/* Ссылки отличаются не только цветом, но и подчёркиванием */
a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
}

VII. Автоматизированная проверка

Интеграция с axe-core

import { axe, toHaveNoViolations } from 'jest-axe';

expect.extend(toHaveNoViolations);

test('цветовая доступность', async () => {
  const { container } = render(<MyComponent />);
  const results = await axe(container);
  expect(results).toHaveNoViolations();
});

Аудит с Lighthouse

npx lighthouse https://example.com --only-categories=accessibility

Интеграция CI

- name: Accessibility check
  run: npx pa11y https://staging.example.com

VIII. Список лучших практик

  1. Контрастность текста ≥ 4,5:1 (обычный текст уровень AA)
  2. Не полагаться только на цвет для передачи информации о состоянии
  3. Использовать дружественную для дальтоников палитру (например, палитру Wong)
  4. Добавлять текстуры/узоры в диаграммы для различения
  5. Сохранять контрастность в тёмном режиме, избегать чисто чёрного фона
  6. Ссылки имеют подчёркивание или другое нецветовое отличие
  7. Сообщения об ошибках имеют текстовое описание, не только красный цвет
  8. Автоматизированные тесты доступности интегрированы в CI
#无障碍#WCAG#对比度#色盲#色彩设计