С чего начать проверку
Практический старт: три проверки, которые не требуют ни бюджета, ни согласований и находят большую часть реальных проблем.
Аудит доступности — не один прогон анализатора, а три независимых прохода: клавиатурой, автоматикой и скринридером. Каждый из них видит то, чего не видят два других.
Хорошая новость: чтобы начать, не нужно ни закупать инструменты, ни звать эксперта. Всё, что нужно для первой проверки, уже стоит у вас на машине. Плохая новость: если ограничиться самым простым шагом — автопроверкой — вы получите зелёную галочку и ложное чувство выполненного долга. Поэтому идём по порядку, от самого честного метода к самому автоматизированному.
Шаг 1. Пройти сайт только клавиатурой
Пятнадцать минут, ноль установок, самая высокая отдача из трёх шагов. Уберите руку с мыши — буквально, положите её на колено — и попробуйте выполнить главный сценарий сайта: найти товар, положить в корзину, оформить.
| Клавиша | Что делает |
Tab / Shift+Tab | вперёд и назад по интерактивным элементам |
Enter | ссылка, кнопка, отправка формы |
Пробел | кнопка, чекбокс, прокрутка страницы |
| Стрелки | радиокнопки, селекты, вкладки, меню |
Esc | закрыть модалку, выпадающий список |
За чем следить:
- Фокус видно? Если после нажатия
Tabвы не понимаете, где находитесь, — это провал критерия 2.4.7. Обычно виноват один и тот же кусок CSS, который кто-то когда-то скопировал из «сброса стилей». - Порядок логичен? Фокус должен идти сверху вниз и слева направо, а не прыгать из подвала в шапку. Прыжки — почти всегда следствие
position: absoluteилиorderво flex, которые визуально переставили элементы, не тронув DOM. - Нет ловушек? Из модального окна и виджета чата фокус должен уметь выйти по
TabилиEsc. Классическая ловушка: открыли модалку, аTabуводит фокус на страницу под ней — вы «печатаете» вслепую в невидимую форму. - Достижимо всё? Карусели, кастомные селекты, «три точки» с меню, крестики закрытия — самые частые места, куда с клавиатуры просто не попасть.
- Есть ли skip link? Ссылка «Перейти к содержимому» экономит клавиатурному пользователю тридцать нажатий
Tabсквозь меню на каждой странице.
<body>
<a class="skip-link" href="#main">Перейти к содержимому</a>
<header>…навигация…</header>
<main id="main" tabindex="-1">…контент…</main>
</body>
/* Ссылка спрятана, пока на неё не пришёл фокус */
.skip-link {
position: absolute;
left: -9999px;
}
.skip-link:focus {
left: 8px;
top: 8px;
z-index: 100;
padding: 8px 16px;
background: #ffffff;
}
/* Так делать нельзя: убивает фокус для всех */
*:focus { outline: none; }
/* Так правильно: заметная рамка тем, кто пришёл с клавиатуры */
:focus-visible {
outline: 3px solid #0b57d0;
outline-offset: 2px;
}
Два бытовых нюанса. На macOS в Safari и Firefox обход по Tab всех элементов надо сначала включить (Системные настройки → Клавиатура → «Навигация с клавиатуры»), иначе фокус будет прыгать только по полям ввода, и вы решите, что сайт сломан. А чтобы видеть, куда фокус уходит на самом деле, удобно бросить в консоль браузера три строки:
// Вставьте в консоль DevTools и нажимайте Tab:
// в консоль будет печататься элемент, на котором сейчас фокус
document.addEventListener('focusin', () => {
console.log(document.activeElement);
});
Это спасает, когда фокус улетает в скрытый элемент: визуально «ничего не подсвечено», а в консоли видно, что фокус сидит в закрытом меню.
Шаг 2. Прогнать автоматический анализатор
Теперь самое дешёвое. Два инструмента покрывают почти все потребности:
- axe DevTools — расширение для Chrome/Firefox от Deque, отраслевой стандарт. Даёт список нарушений с номером критерия WCAG, подсветкой элемента и объяснением, как чинить.
- Lighthouse — уже встроен в Chrome DevTools, вкладка Lighthouse, категория Accessibility. Под капотом использует тот же axe-core, но проверяет меньше правил.
- WAVE — расширение, которое рисует иконки проблем прямо поверх страницы. Удобно показывать дизайнеру и менеджеру: видно, где болит.
Для регулярных прогонов и CI есть консольные версии:
# Lighthouse только по разделу «Доступность», с отчётом в браузере
npx lighthouse https://example.com --only-categories=accessibility --view
# axe-core по странице, с фильтром по нужным уровням WCAG
npx @axe-core/cli https://example.com --tags wcag2a,wcag2aa
# pa11y — удобен для списка страниц и порога «сколько ошибок допустимо»
npx pa11y https://example.com --standard WCAG2AA
Автоматика отлично ловит то, что выражается числом или наличием атрибута: контраст, отсутствующий alt, поле без <label>, отсутствующий lang, дублирующиеся id, несуществующие ARIA-атрибуты, пропуски в иерархии заголовков. Это буквально топ причин из отчёта WebAIM Million — то есть за десять минут вы снимаете самый массовый пласт проблем. Начинать надо именно с них.
Шаг 3. Включить скринридер
Самый пугающий шаг — и самый отрезвляющий. Ставить ничего не нужно:
| Платформа | Скринридер | Как включить |
| macOS | VoiceOver | Cmd + F5 |
| Windows | NVDA (бесплатный, самый популярный) или встроенный «Экранный диктор» | скачать nvaccess.org / Win + Ctrl + Enter |
| iOS / Android | VoiceOver / TalkBack | в настройках специальных возможностей |
Первые пять минут будет громко и непонятно — это нормально, регулятор скорости речи существует. Минимальная программа: закройте глаза (или выключите монитор) и пройдите ту же задачу, что и в шаге 1. Слушайте не «красиво ли», а три вещи:
- Есть ли у элемента имя. Если вместо «Закрыть, кнопка» звучит просто «кнопка» — у неё нет доступного имени: иконка без
aria-label. - Верна ли роль. Если «В корзину» озвучено как обычный текст, а не как «кнопка», значит перед вами тот самый
<div>из первого урока. - Объявляются ли изменения. Нажали «Добавить в корзину» — счётчик изменился визуально, а скринридер промолчал. Пользователь не знает, сработало ли. Это критерий 4.1.3, лечится живой областью:
<!-- Текст, попавший сюда, будет озвучен без перевода фокуса -->
<div role="status" aria-live="polite">Товар добавлен в корзину</div>
<!-- Иконочная кнопка без текста обязана иметь доступное имя -->
<button type="button" aria-label="Закрыть диалог">
<svg aria-hidden="true" focusable="false">…</svg>
</button>
Полезно освоить ровно одну «продвинутую» команду — список заголовков или ссылок (в NVDA это Insert + F7, в VoiceOver — ротор по Ctrl + Option + U). Именно так реальные пользователи и навигируют: не слушают страницу подряд, а прыгают по структуре. Если в вашем списке заголовков сплошные «Заголовок 3» и ни одного осмысленного — навигация по сайту невозможна, хотя автопроверка была зелёной.
Как это работает: почему автоматика ловит меньше половины
Оценки расходятся (от трети до примерно половины проблем в зависимости от методики), но вывод у всех один: анализатор не заменяет человека. Причина не в качестве инструментов, а в природе критериев. Их можно разделить на два класса:
- Машинно-проверяемые: есть ли атрибут, каково число. «Контраст 3.1:1 меньше 4.5:1» — тут машина безупречна и не устаёт.
- Требующие понимания смысла: «текстовая альтернатива описывает изображение», «порядок фокуса логичен», «назначение ссылки понятно». Машина проверяет наличие, человек — осмысленность.
Отсюда фундаментальный разрыв. Атрибут alt="IMG_20240517.jpg" формально удовлетворяет критерию 1.1.1: альтернатива есть. Двадцать ссылок «Подробнее» подряд проходят автопроверку, а в списке ссылок скринридера превращаются в двадцать одинаковых строк. Модалка с идеальным контрастом и всеми aria-label может намертво держать фокус — axe об этом не узнает, потому что не нажимает Tab.
| Проблема | Автопроверка | Клавиатура | Скринридер |
| Контраст текста 3:1 | да | нет | нет |
Картинка без alt | да | нет | да |
alt="photo1.png" | нет | нет | да |
| Ловушка фокуса в модалке | нет | да | да |
Нелогичный порядок Tab | нет | да | частично |
Кнопка-div без роли | частично | да | да |
| Добавление в корзину не объявлено | нет | нет | да |
Посмотрите на колонки: ни одна не покрывает таблицу целиком. Поэтому три шага — не «уровни зрелости», а три разных сенсора, и нужны все три.
Частые ошибки
- Гнаться за «100» в Lighthouse. Сотня означает «не найдено автоматически обнаружимых нарушений на этой странице», а не «сайт доступен». Страница, состоящая из одних
<div>без единого интерактивного элемента, легко берёт 100 баллов. - Проверять только главную. Барьеры живут в формах, корзине, личном кабинете и модалках — там, где логика, а не в баннере с котом.
- Чинить симптом, а не причину. Увидели «кнопка без имени» — не спешите вешать
aria-labelна<div>. Сначала спросите, почему это не<button>. - Проверять скринридером «как удобно вам». Вы читаете страницу подряд, реальный пользователь — прыгает по заголовкам и ссылкам. Проверяйте так, как ходят они.
- Ставить оверлей вместо исправлений. Виджет, который «включает доступность одной строчкой скрипта», не превращает
<div>в кнопку и не пишет за вас осмысленныйalt.
Итоги
Программа первых тридцати минут на любом проекте:
[ ] 10 мин — пройти главный сценарий только клавиатурой:
фокус видно / порядок логичен / Esc закрывает / ловушек нет
[ ] 10 мин — прогнать axe DevTools или Lighthouse на 3–5 ключевых страницах,
выписать нарушения контраста, alt, label, lang
[ ] 10 мин — включить VoiceOver или NVDA, послушать одну форму:
у всех ли кнопок есть имя, объявляются ли ошибки и успех
- Клавиатура — самый честный и дешёвый тест, начинайте с него.
- Автопроверка (axe, Lighthouse, WAVE) снимает массовый пласт: контраст, alt, label, lang — но это лишь часть проблем.
- Скринридер показывает то, что не видит ни один анализатор: бессмысленные имена, немые кнопки, необъявленные изменения.
- Автоматика не заменяет человека, потому что половина критериев требует понимания смысла, а не проверки атрибута.
- Зелёный отчёт — это начало разговора о доступности, а не его конец.