Доступная навигация с клавиатуры в небольшом веб-приложении

Схема навигации с видимым фокусом на кнопке и ссылках

Для небольшой навигации обычно достаточно ссылок и кнопки раскрытия. Роли menu и menubar не следует добавлять только из-за привычного слова «меню»: они подразумевают другой сложный контракт. Покажем простую навигацию, в которой Tab продолжает работать обычным образом.

Рабочая навигация с кнопкой раскрытия

index.html

<!doctype html>
<html lang="ru"><meta charset="utf-8"><title>Навигация</title>
<nav aria-label="Основная">
<button id="nav-button" type="button" aria-expanded="false" aria-controls="links">Разделы</button>
<ul id="links" hidden><li><a href="#news">Новости</a></li><li><a href="#guides">Гайды</a></li></ul>
</nav><main><h1>Учебная страница</h1><h2 id="news">Новости</h2><h2 id="guides">Гайды</h2></main>
<script>
const button = document.querySelector('#nav-button');
const links = document.querySelector('#links');
function setOpen(open) {
  button.setAttribute('aria-expanded', String(open));
  links.hidden = !open;
}
button.addEventListener('click', () => setOpen(links.hidden));
document.querySelector('nav').addEventListener('keydown', event => {
  if (event.key === 'Escape' && !links.hidden) {
    setOpen(false); button.focus();
  }
});
</script></html>

Откройте файл и пройдите его без мыши. Tab приводит к кнопке, Enter или Space раскрывает ссылки, следующие нажатия Tab переводят фокус по ним. Escape в открытой области закрывает список и возвращает фокус к кнопке. Дополнительный Escape — выбранное удобство примера; базовое раскрытие опирается на паттерн WAI-ARIA APG.

Слои доступности
Что сравнить На что смотреть Что сделать
Семантика nav, button и a Сохранить назначение каждого элемента
Состояние aria-expanded Сообщать раскрытие синхронно с видимостью
Порядок Естественное расположение DOM Не переставлять фокус произвольно
Возврат Закрываемая область может содержать фокус Вернуть его в видимый логичный элемент

Не прячьте фокус вместе со ссылками

Если список закрывают программно, пока фокус находится внутри него, нужно определить последующее место. В примере закрытие по Escape явно переводит фокус на кнопку. Для закрытия по выбору ссылки поведение зависит от перехода: не добавляйте автоматический возврат, если пользователь уже ушёл на другую страницу или в целевой раздел.

  • Проверить раскрытие Enter и Space.
  • Проверить Tab и Shift+Tab.
  • Закрыть список из вложенной ссылки через Escape.
  • Проверить заметность стандартного или собственного фокусного контура.

Не задавайте положительные tabindex ради желаемого порядка и не отключайте outline без равнозначной видимой замены. Для большего интерфейса сначала выберите подходящий паттерн, затем проверяйте его в целевых браузерах и с нужными вспомогательными средствами. Наличие нескольких ARIA-атрибутов само по себе не означает полного аудита доступности.

Вопросы и ответы

Нужны ли стрелки для обычных ссылок?

Не обязательно. В этой простой навигации используется стандартный Tab, а не поведение составного menu.

Почему у кнопки type="button"?

Так она не станет неожиданно отправлять форму, если компонент позже окажется внутри неё.

Список скрывается только визуально?

В примере используется hidden, а не прозрачность. Состояние должно соответствовать реальной доступности содержимого.

Можно ли считать пример полностью проверенным на всех устройствах?

Нет. Это основа для локальной проверки; продукт требует проверки в своём окружении и сценариях.

Источники: w3.org.

Похожие записи