Skip to content
Иван Ткаченко Блог
EN
Базовый accessibility — Иван Ткаченко ← К статьям
Frontend

Базовый accessibility

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

На первый взгляд кажется, что это крайний случай: кто вообще логинится без мыши. Но после нескольких лет без мыши начинаешь невольно замечать проблемы с клавиатурной навигацией везде. Открываешь форму Tab-ом и сразу видишь, что выделение фокуса исчезло, после нажатия Tab фокус прыгнул не туда, кнопка Submit вообще недоступна без мыши.

Accessibility часто воспринимают как “для людей с ограниченными возможностями”, но точнее это про ситуативные ограничения. На практике базовый уровень не такой большой:

Видимое выделение фокуса. Когда элемент в фокусе, это должно быть заметно. Браузер рисует стандартный outline, который многие разработчики сбрасывают через outline: none и ничего не добавляют взамен.

/* ❌ */
:focus {
  outline: none;
}

/* ✅ */
:focus-visible {
  outline: 2px solid #0066cc;
}

Логичная последовательность Tab. Порядок, в котором клавиатура обходит элементы, должен совпадать с визуальным порядком на странице. Если макет построен через абсолютное позиционирование или flex с order, порядок в DOM и на экране могут расходиться. Пройди форму Tab-ом — если фокус прыгает непредсказуемо, порядок навигации сломан.

Подписи для иконок-кнопок. Иконка без текста должна иметь aria-label, скринридер объявит её как “button” и замолчит, пользователь не поймёт, что это за кнопка.

<!-- ❌ -->
<button><svg>...</svg></button>

<!-- ✅ -->
<button aria-label="Закрыть"><svg>...</svg></button>

Цветовой контраст. Серый текст на светлом фоне читается плохо — и не только людьми с нарушением зрения: солнечный свет, усталость, маленький экран. Минимум по WCAG: 4.5:1 для обычного текста, 3:1 для крупного. Lighthouse поможет выявить такие проблемы.

Семантика. Кнопка должна быть <button>, а не <div> с onclick. Поле должно быть связано с <label> через for/id: тогда клик по тексту метки фокусирует поле, и скринридер озвучивает её при переходе к нему.

<!-- ❌ -->
<div onclick="submit()">Отправить</div>
<input id="email" />

<!-- ✅ -->
<button type="submit">Отправить</button>
<label for="email">Email</label>
<input id="email" />

alt для изображений. Если картинка несёт смысл, нужен описательный alt. Если декоративная, ставим alt="", чтобы скринридер её пропустил, а не читал имя файла.

<!-- ❌ -->
<img src="chart.png" />

<!-- ✅ смысловая -->
<img src="chart.png" alt="Продажи выросли на 40% в Q3" />

<!-- ✅ декоративная -->
<img src="divider.svg" alt="" />

Не передавать смысл только цветом. Ошибка, выделенная красным без текста или иконки: люди с нарушением цветового восприятия её не заметят.

Ошибки форм. Привязка сообщения об ошибке к полю через aria-describedby позволяет скринридеру озвучить конкретную ошибку, а не просто факт её наличия.

<!-- ❌ -->
<input id="email" aria-invalid="true" />
<p>Введите корректный email</p>

<!-- ✅ -->
<input id="email" aria-invalid="true" aria-describedby="email-error" />
<p id="email-error">Введите корректный email</p>

Skip link. Первая ссылка на странице, визуально скрытая, которая перебрасывает сразу к основному контенту. Без неё пользователи клавиатуры на каждой странице Tab-ают через всю навигацию.

<a href="#main" class="skip-link">Перейти к основному контенту</a>
.skip-link {
  position: absolute;
  top: -100%;
}
.skip-link:focus {
  top: 0;
}

Анимации. Часть пользователей физически плохо переносит анимации на экране. Один медиа-запрос решает это.

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }
}

Модальные окна. При открытии фокус переходит на первый элемент формы или кнопку закрытия, при закрытии возвращается на элемент, который модалку открыл. Без этого пользователь теряется в навигации. Звучит очевидно, но на практике часто на это забивают.

Большинство этих проблем не находят просто потому, что про них не думают в процессе разработки и не тестируют. И напрасно, потому что это такая же характеристика продукта, как performance или отсутствие багов, и напрямую влияет на то, насколько удобно им пользоваться.

Кстати, в США из-за нарушений accessibility на сайтах было подано тысячи исков по закону ADA. В Европе European Accessibility Act вступил в полную силу в 2025 году. Во многих странах это уже законодательное требование, а не рекомендация.