Доступность (a11y) в вебе: как сделать сайт удобным для всех пользователей

Веб доступность a11y - это набор практик, которые делают сайт понятным, управляемым и предсказуемым для людей с разными возможностями и устройствами: клавиатурой, скринридером, увеличением текста, альтернативными методами ввода. Внедряйте доступность как процесс: начните с аудита, исправьте семантику HTML, обеспечьте корректный фокус и клавиатурную навигацию, затем проверьте контраст и ARIA и регулярно выполняйте тестирование.

Краткий план внедрения доступности

  • Критично: выполните аудит доступности сайта на ключевых шаблонах (главная, каталог/листинг, карточка, форма, модальные окна).
  • Критично: поправьте семантику и структуру (заголовки, landmark-области, подписи полей, названия кнопок/ссылок).
  • Критично: обеспечьте полную навигацию с клавиатуры и видимый фокус, включая модальные окна и выпадающие меню.
  • Важно: проверьте визуальную доступность (контраст, цвет как единственный носитель смысла, масштабирование текста).
  • Важно: используйте ARIA только там, где нет нативного HTML-решения; проверьте динамику и объявления статуса.
  • Опционально: подключите регулярное тестирование доступности сайта в CI и проводите периодические ручные проверки.

Аудит доступности: чеклист для оценки текущего сайта

Кому подходит: командам, которые улучшают существующий продукт, готовят редизайн или хотят снизить риск регрессий перед релизом. Аудит особенно полезен, если есть формы, личный кабинет, сложная навигация, много динамики (SPA), контент от редакторов.

Когда не стоит делать прямо сейчас: если сайт в полном переписывании и нет стабильных шаблонов; если нет доступа к коду/дизайну и нельзя вносить изменения; если вы ищете разовую отметку вместо процесса (в этом случае разумнее заранее планировать разработку доступного сайта в дизайн-системе и компонентах).

  • Критично: можно ли пройти все сценарии только клавиатурой (Tab/Shift+Tab/Enter/Space/Esc)?
  • Критично: есть ли видимый фокус на интерактивных элементах?
  • Критично: у полей формы есть связка и id, а ошибки сообщаются текстом и привязаны к полю.
  • Важно: структура заголовков логична (h1h2h3 без скачков ради стиля).
  • Важно: изображения со смыслом имеют alt, декоративные - пустой alt="".
  • Важно: нет интерактива на <div>/<span> без роли, имени и поддержки клавиатуры.

Если вы не внедряете всё сами, формулируйте результат как набор дефектов и требований - так проще оценить услуги по доступности сайта у подрядчиков: список проблем, приоритет, критерий приёмки и страницы/компоненты, где воспроизводится.

Семантика и структура: как HTML улучшает доступность

Основа доступности - нативный HTML: он уже корректно работает со скринридерами, клавиатурой и фокусом. ARIA - дополнение, а не замена. Ориентируйтесь на принципы WCAG (воспринимаемость, управляемость, понятность, надёжность) и закрывайте ключевые места уровня A/AA там, где есть пользовательские действия.

Что понадобится для работы с семантикой

  • Доступы: к репозиторию/шаблонам, дизайн-макетам и списку страниц (роутов), где есть основные сценарии.
  • Инструменты: DevTools, инспектор accessibility tree (Chrome/Firefox), линтеры (например, eslint-plugin-jsx-a11y для React), валидатор HTML.
  • Проверки: инструменты вроде axe DevTools, Lighthouse, WAVE (как подсказки, не как окончательное решение).
  • Тест-окружение: возможность прогонять изменения на стейдже, чтобы увидеть реальные ошибки форм, статусы и состояния.

Быстрые семантические правки с максимальным эффектом

  • Landmarks: используйте <header>, <nav>, <main>, <footer>; при нескольких навигациях добавляйте aria-label на <nav>.
  • Кнопки и ссылки: действие -

    <section id="filters" hidden>
    ...
    </section>

    Навигация с клавиатуры и управление фокусом: практические паттерны

    Цель - чтобы пользователь мог пройти ключевые сценарии без мыши, не теряя позицию фокуса, и чтобы состояния компонентов были понятны через доступное имя/роль/состояние.

    Подготовка к правкам фокуса и клавиатуры

    • Выберите 2-3 критичных сценария (поиск, оформление, отправка формы) и привяжите к ним критерии приёмки.
    • Соберите список всех кастомных компонентов (модалки, меню, табы, аккордеоны, автокомплиты).
    • Проверьте, где используется глобальное отключение outline и какие стили :focus/:focus-visible реально применяются.
    • Определите единый подход: где применяете нативные элементы, а где допускаете ARIA-паттерны.
    • Договоритесь, как фиксировать дефекты: шаги воспроизведения, ожидаемое поведение, фактическое поведение, приоритет.
    1. Запретите недоступный интерактив. Проверьте, что кликабельные элементы - это нативные <button>/<a>, а не <div>/<span> с обработчиком. Нативные элементы сразу дают правильную клавиатуру и базовые роли.

      • Критично: не добавляйте tabindex="0" на контейнеры ради кликабельности.
      • Важно: если компонент неизбежно кастомный, зафиксируйте, какой ARIA-паттерн применяете (например, disclosure для раскрытия).
    2. Сделайте порядок Tab предсказуемым. Уберите tabindex больше 0 и не используйте его для перестановки фокуса по странице. Допускайте tabindex="-1" только для программной фокусировки контейнера, куда реально нужно переместить пользователя.
    3. Обеспечьте видимый фокус. Задайте заметный стиль для :focus/:focus-visible и не удаляйте outline глобально без замены. Фокус должен оставаться видимым на разных фонах, в hover/active/disabled-состояниях.
    4. Добавьте ссылку для перехода к основному содержимому. Разместите skip link в начале страницы, чтобы по клавиатуре можно было быстро перейти в <main>. Целевой элемент при необходимости сделайте фокусируемым, например tabindex="-1".
    5. Настройте модальные окна как диалоги. При открытии переводите фокус внутрь модалки, удерживайте Tab в пределах диалога, закрывайте по Esc и возвращайте фокус в элемент-триггер. Кнопка закрытия должна иметь понятное доступное имя.

      • Критично: фон за модалкой не должен попадать в таб-цепочку.
      • Важно: заголовок модалки должен быть объявлен для скринридера (например, через aria-labelledby).
    6. Сделайте раскрывающиеся меню и поповеры управляемыми. Триггер делайте кнопкой с aria-expanded и привязкой области через aria-controls. В закрытом состоянии скрывайте содержимое так, чтобы оно не читалось и не фокусировалось.
    7. После действий переводите фокус осмысленно. После отправки формы, появления ошибок или смены шага переводите фокус на заголовок секции или статус. Не перемещайте фокус без причины, чтобы не дезориентировать пользователя.

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

    • Критично: текст и интерактивные элементы имеют достаточный контраст с фоном (ориентируйтесь на WCAG 2.x, уровень AA).
    • Критично: смысл не передаётся только цветом (ошибка, успех, выбранное состояние имеют текст/иконку/паттерн).
    • Критично: состояния фокуса/выделения заметны и не зависят только от изменения оттенка.
    • Важно: при увеличении масштаба и размера шрифта интерфейс остаётся читаемым, не ломает сценарии и не прячет кнопки.
    • Важно: кликабельные зоны достаточно крупные, чтобы ими было удобно пользоваться на тач-устройствах.
    • Важно: ссылки визуально отличимы от обычного текста не только цветом (например, подчёркивание или иной устойчивый признак).
    • Опционально: анимации не мешают восприятию; для сильных эффектов учитывайте предпочтение prefers-reduced-motion.

    ARIA и динамический контент: правильное применение и ошибки

    • Критично: не используйте ARIA для имитации нативных элементов, если можно применить нативный HTML (правило: first rule of ARIA).
    • Критично: не добавляйте role на элементы, у которых роль уже есть по умолчанию, без необходимости (можно сломать семантику).
    • Критично: следите за доступным именем: aria-label и видимый текст должны совпадать по смыслу, иначе голосовой ввод и подсказки будут путать.
    • Важно: aria-expanded, aria-pressed, aria-selected обязаны отражать реальное состояние, а не дизайн-ожидание.
    • Важно: aria-controls должен указывать на существующий id; не оставляйте битые связи.
    • Важно: для ошибок и статусов используйте корректные объявления (например, role="status" или aria-live), но избегайте чрезмерных live-областей.
    • Важно: не делайте скрытый контент доступным для скринридера, если он не должен читаться (согласуйте hidden/aria-hidden и состояние компонента).
    • Опционально: не злоупотребляйте tabindex="-1" и программной фокусировкой: фиксируйте правила, когда это допустимо.

    Тестирование и приоритизация исправлений: автоматические и пользовательские проверки

    Доступность (a11y) в вебе: как сделать сайт удобным для всех - иллюстрация

    Тестирование доступности сайта удобно строить как воронку: сначала быстрые автоматические подсказки, затем ручные проверки и при необходимости пользовательское тестирование со скринридером. Приоритизируйте по влиянию на ключевые сценарии и частоте использования.

    Альтернативы, которые можно сочетать в зависимости от зрелости команды

    1. Автоматизированные проверки (быстро, но неполно). Подходят для регулярного контроля регрессий: axe/Lighthouse, линтеры, unit/e2e-тесты на роли/имена.
    2. Ручная проверка клавиатурой и фокусом (наиболее окупаемая). Уместна всегда: выявляет ловушки фокуса, невидимые состояния, проблемы модалок/меню, которые автоматикой часто не ловятся.
    3. Проверка со скринридером (точечно по сценариям). Уместна для форм, навигации, каталога, сложных компонентов; фиксируйте, что читает скринридер в ключевых местах (названия, состояния, ошибки).
    4. Внешний аудит/консалтинг. Уместно, когда нужна независимая оценка, нет компетенции внутри или требуются услуги по доступности сайта для сложной системы; просите отчёт с воспроизведением, приоритетом и критериями приёмки.

    Практика приоритизации: сначала блокеры (невозможно оформить заказ, отправить форму, закрыть модалку с клавиатуры), затем массовые проблемы шаблонов (кнопки, ссылки, подписи, фокус), затем точечные улучшения. Так разработка доступного сайта остаётся управляемой и предсказуемой.

    Разрешение типичных затруднений по доступности

    С чего начать, если сайт большой и старый?

    Начните с аудита доступности сайта на нескольких ключевых шаблонах и основных сценариях. Исправляйте сначала семантику, формы и клавиатурную навигацию - это обычно даёт наибольший эффект.

    Достаточно ли автоматических инструментов для соответствия WCAG?

    Нет: автоматизация находит только часть проблем. Добавьте ручные проверки клавиатурой и точечное тестирование доступности сайта со скринридером по критичным сценариям.

    Когда использовать ARIA, а когда лучше не трогать?

    Используйте ARIA, когда нативного HTML недостаточно для описания роли или состояния компонента. Не применяйте ARIA там, где можно использовать нативные <button> и <a>.

    Почему нельзя просто убрать outline у фокуса?

    Потому что пользователи клавиатуры теряют ориентир, где находятся на странице. Если стандартный стиль не подходит, замените его на другой заметный фокус-стиль, но не отключайте полностью.

    Как понять, что компонент действительно доступен с клавиатуры?

    Все действия выполняются Tab/Shift+Tab/Enter/Space, есть видимый фокус и нет ловушек. Состояния (раскрыто, выбрано, нажато) корректно отражаются и не требуют мыши.

    Когда имеет смысл привлекать подрядчика?

    Если интерфейс сложный, внутри нет опыта или нужна независимая проверка перед крупным релизом, подрядчик ускорит диагностику. Запрашивайте отчёт с воспроизведением, приоритетами и критериями приёмки.

    Как встроить доступность в процесс разработки, чтобы не откатываться назад?

    Закрепите правила в дизайн-системе и код-ревью, добавьте линтеры и минимальные проверки в CI. Тогда улучшения превращаются в процесс, а не в разовую задачу.

Прокрутить вверх