Цветовая доступность: контраст, дальтонизм и соответствие 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
Шаги использования
- Откройте инструмент цветового контраста
- Введите цвет переднего плана и фона (поддерживает HEX, RGB, HSL)
- Просмотрите результаты:
- Коэффициент контрастности
- Статус соответствия WCAG AA / AAA
- Отдельная оценка для обычного текста / крупного текста
- Корректируйте цвета до соответствия
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. Список лучших практик
- Контрастность текста ≥ 4,5:1 (обычный текст уровень AA)
- Не полагаться только на цвет для передачи информации о состоянии
- Использовать дружественную для дальтоников палитру (например, палитру Wong)
- Добавлять текстуры/узоры в диаграммы для различения
- Сохранять контрастность в тёмном режиме, избегать чисто чёрного фона
- Ссылки имеют подчёркивание или другое нецветовое отличие
- Сообщения об ошибках имеют текстовое описание, не только красный цвет
- Автоматизированные тесты доступности интегрированы в CI
#无障碍#WCAG#对比度#色盲#色彩设计