Один макет видят по-разному: кто-то увеличил системный шрифт, кто-то смотрит через лупу на 200%, кто-то включил высококонтрастный режим, кто-то отключил анимации из-за вестибулярных проблем, кто-то открыл сайт на узком телефоне. Интерфейс страницы товара должен пережить все эти настройки, а не только вид из макета.
Наивный подход - собрать пиксель-в-пиксель под один идеальный экран. Естественно: так выглядит утверждённый макет, на нём всё красиво, и кажется, достаточно точно повторить его в вёрстке.
Ломается это на первой же настройке. При увеличении текста до 200% (1.4.4) фиксированные высоты обрезают строки; на узком экране контент должен переверстаться в одну колонку без горизонтальной прокрутки (1.4.10 - reflow до 320px); при заданных интервалах текст не должен налезать сам на себя (1.4.12); а в forced-colors система выбрасывает ваши цвета и ставит свои - и всё, что держалось на цвете, рассыпается.
Первое, что проверяют, - контраст. Обычный текст обязан отличаться от фона как 4.5:1, крупный (от 24px или 18.66px жирного) - как 3:1 (1.4.3). Но правило шире: границы полей, иконки, индикатор фокуса и состояния дают не меньше 3:1 к соседнему цвету (1.4.11). Бледно-красная цена скидки на белом стильна и проваливает оба порога.
| Что | Минимальный контраст |
|---|---|
| Обычный текст | 4.5:1 |
| Крупный текст (24px или 18.66px жирный) | 3:1 |
| Иконки, границы, индикатор фокуса | 3:1 |
Цвет не должен быть единственным носителем смысла (1.4.1). Если 'нет в наличии' показано только серым, дальтоник не отличит - нужен текст или значок. То же с ошибками формы и обязательными полями: рядом с цветом всегда дублирующий текст или иконка.
Движение - отдельная забота. У части людей анимация вызывает тошноту и головокружение (вестибулярные нарушения), поэтому система шлёт запрос prefers-reduced-motion: reduce, и его надо уважать - гасить параллакс, автопрокрутку каруселей, резкие переходы (2.3.3 и 2.2.2). И движение не должно быть единственным носителем смысла: если статус загрузки виден только по вращению спиннера, без анимации он исчезает.
Промо-ролик несёт ещё три требования. Речь в видео дублируют субтитрами - иначе глухой не получит содержания (1.2.2); желателен и текстовый транскрипт. Важную визуальную информацию, не проговорённую вслух, дают аудиоописанием (1.2.5). Звук не должен включаться сам, а у плеера обязаны быть кнопки паузы и громкости (1.4.2).
Изображения делятся на два класса. Декоративная - фон, разделитель, украшение - получает пустой alt, чтобы диктор её пропустил и не читал имя файла. Содержательная - фото товара, значок скидки, схема размеров - получает краткую функциональную альтернативу: не 'IMG_2043', а что изображение сообщает и зачем оно здесь (1.1.1).
Плата за всё это - тестирование в нескольких режимах, а не в одном браузере на большом мониторе. Проверять надо не только текст, но и иконки, границы полей, индикатор фокуса и состояния - именно они чаще всего проваливают контраст. Это рутина, которую легко пропустить под дедлайн, но она и есть разница между 'работает у меня' и 'работает у всех'.
Типичный провал собирается из мелочей: слабовидящий увеличивает страницу до 200%, вёрстка ломается в горизонтальную прокрутку, цена скидки не читается из-за бледного цвета, а промо-ролик автозапускается со звуком и без субтитров. Каждая деталь по отдельности кажется косметической - вместе они выкидывают человека из покупки. Поэтому визуальную доступность проверяют в условиях, в каких живут пользователи: с лупой, крупным шрифтом, отключённой анимацией и в высококонтрастном режиме.
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: .01ms !important;
animation-iteration-count: 1 !important;
transition-duration: .01ms !important;
transition-delay: -1ms !important;
scroll-behavior: auto !important;
}
}