Клавиатура и диктор: имя, роль, состояние

Зачем:Человек с диктором не видит страницу, а слушает её дерево: у каждого элемента есть имя, роль и состояние. После урока вы понимаете, как браузер собирает это дерево, делаете кнопку меню, окно и навигацию, с которыми справляются клавиатура и диктор, и умеете за пять минут проверить свою страницу NVDA или VoiceOver.

30 минут

Озвучено синтезом речи (Qwen3-TTS), голос не принадлежит человеку.

Дерево доступности — то, что браузер строит из разметки для диктора: у каждого элемента есть имя, роль и состояние. Нативные элементы дают их сами.

Страница, которую слушают

Человек, который не видит экран, не «слушает картинку». Он слушает дерево доступности: параллельное дерево, которое браузер строит из вашей разметки специально для вспомогательных программ. В нём у каждого элемента есть три вещи:

  • имя (name): как он называется. У кнопки «Меню», у поля «Телефон», у картинки её альтернативный текст;
  • роль (role): что это такое. Ссылка, кнопка, заголовок, поле, список, навигация;
  • состояние (state): в каком он положении. Раскрыто, нажато, выбрано, текущая страница, ошибка.

Диктор (программа чтения с экрана) собирает из них фразу вроде «Меню, кнопка, свёрнуто». Значительная часть доступности интерфейса состоит в том, чтобы эта фраза была верной.

Откуда браузер берёт имя, роль и состояние? Роль и поведение он берёт из самого элемента: button это кнопка, a с href это ссылка, h2 это заголовок второго уровня. Имя собирается по порядку из нескольких мест: aria-labelledby, aria-label, затем содержимое или связанная подпись (label для поля, alt для картинки), и в самую последнюю очередь title. Состояние берётся из атрибутов (checked, disabled, aria-expanded, aria-current).

Вывод, который вы уже знаете из первого урока про ARIA: нативный элемент даёт все три сразу, а div не даёт ни одного. Поэтому чаще всего достаточно выбрать правильный элемент и дать ему имя.

Как слушают страницу

Диктором пользуются иначе, чем читают глазами. По опросу WebAIM (одиннадцатый, лето 2026 года; ответили около 1800 человек) на длинной странице чаще всего начинают с заголовков: так сказали около двух третей. Поэтому в режиме просмотра клавиши быстрой навигации перепрыгивают между однотипными элементами: H к следующему заголовку, D к следующей области, F к следующему полю формы, K к ссылке, B к кнопке. Диктор может показать и список всех заголовков, всех областей, всех ссылок.

Из этого следует то, что вы делаете руками:

  • Заголовки выстроены по порядку, h1 один, и по ним можно понять страницу, как по оглавлению.
  • Области (landmarks) отмечены тем, что вы знаете как смысловые элементы: header, nav, main, aside, footer. Если навигаций две, у каждой своё имя в aria-label: «Разделы сайта», «Подвал».
  • Ссылки понятны вне контекста. «Подробнее» в списке из десяти ссылок звучит десять раз одинаково; пишите «Подробнее об услуге: межевание».
  • Поля подписаны. Без подписи диктор скажет «поле ввода», и человек не знает, что вводить.

Диктор, кстати, разный: по тому же опросу на компьютере чаще всего используют JAWS (платная) и NVDA (бесплатная), в телефонах это VoiceOver у iPhone и TalkBack у Android. Слова у каждой программы немного различаются, а смысл тот же.

Проверьте себя: из чего диктор складывает «Меню, кнопка, свёрнуто»?

Имя «Меню» берётся из содержимого кнопки, роль «кнопка» от самого элемента button, состояние «свёрнуто» от атрибута aria-expanded=“false”.

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

Фокус и порядок вы знаете из первого прохода. Что нужно добавить для сложных элементов.

  • Tab переходит между элементами, Shift+Tab назад. Внутри составных элементов (набор переключателей, вкладки, меню) между пунктами ходят стрелки, а Tab проходит всю группу целиком. Для самодельных виджетов это нужно программировать; руководство ARIA Authoring Practices Guide описывает ожидаемое поведение каждого.
  • Enter нажимает ссылку и кнопку, Пробел нажимает кнопку и ставит флажок, Esc закрывает окно, всплывающее меню или подсказку.
  • Раскрывающиеся блоки проще всего делать кнопкой с aria-expanded и aria-controls: диктор объявит «свёрнуто» или «развёрнуто». Такой шаблон называют disclosure, и им стоит заменять самодельные «меню» с ролью menu, которая обещает больше, чем сделано.
  • Окна. Модальное окно должно: переносить фокус внутрь, не выпускать Tab наружу, закрываться по Esc и возвращать фокус на кнопку, которая его открыла. Нативный элемент dialog с методом showModal() всё это делает сам; достаточно дать ему имя через aria-labelledby.
Проверьте себя: что делает элемент dialog после showModal() для клавиатуры?

Переносит фокус внутрь, делает остальную страницу недоступной, закрывается по Esc и возвращает фокус на кнопку, открывшую окно.

Сообщения: что менялось на странице

Страница меняется без перезагрузки: появилась ошибка, добавился товар в корзину, прошла отправка. Зрячий это замечает, а диктор не знает, куда смотреть. Решение: живые области (live regions). Контейнер с role="status" (вежливо: прочитать, когда диктор освободится) или role="alert" (срочно, прерывая чтение) лежит в странице заранее, а потом в него вставляют текст. Диктор прочтёт вставленное сам, фокус не двигается.

Два правила. Контейнер должен существовать до вставки текста, иначе многие программы не объявят. И не объявляйте всё подряд: десять сообщений за секунду делают страницу невыносимой.

Скрытое: кто что видит

  • display: none и атрибут hidden убирают элемент и для глаз, и для диктора, и для клавиатуры. Так скрывают то, что действительно не нужно (закрытое меню).
  • aria-hidden="true" убирает элемент только для диктора; фокус до него по-прежнему дойдёт. Им скрывают декоративное (иконку рядом с текстом), и никогда не ставят на то, что можно сфокусировать.
  • Класс «только для диктора» (текст сдвинут за край экрана, но остаётся в дереве) нужен для подписи иконке без слов. Часто проще атрибут aria-label.

Схема ниже: три элемента, каждый написан несколькими способами. Смотрите, доходит ли до него Tab, работает ли Enter и что говорит диктор.

Что слышит диктор и что делает Tab

Выберите элемент и способ, которым он написан. Справа видно, что с ним делают клавиатура и диктор. Слова диктора условны: каждая программа говорит чуть иначе, но смысл тот же.

<div onclick="open()">Меню</div>
Tab доходит
✕ нет
Enter и Пробел работают
✕ нет
Диктор говорит
«Меню» (обычный текст, роль не названа)
Вывод
Мышью работает, клавиатурой и диктором нет: фокус сюда не доходит.

Текстовая альтернатива: схема показывает для кнопки меню, поля и окна, как разные способы разметки ведут себя с клавиатурой и с диктором. Нативные элементы (button, label с input, dialog) получают фокус, управляются клавишами и называются сами; div с обработчиком клика и ролью требует дописывать всё это вручную.

Проверка за пять минут

Включите диктор: NVDA для Windows бесплатен, в macOS VoiceOver включается сочетанием Command+F5. Затем:

  1. Закройте глаза или отвернитесь от монитора (или погасите экран).
  2. Клавишей H пройдите по заголовкам: складывается ли оглавление?
  3. Клавишей D пройдите по областям: есть ли навигация и основное?
  4. Дойдите до формы клавишей F. Услышали ли вы подпись каждого поля?
  5. Выполните главное действие из брифа (запись, заказ). Дошли? Услышали ли результат?

Не получилось что-то из пунктов, значит, это приоритет для исправления. Для первого раза не нужно знать все команды: достаточно этих пяти клавиш.

Практика

Вы остаётесь в эпохе 2014 года. На странице меню и окно сделаны из div, и работают они только мышью. Перепишите их нативными элементами и запишите в заметке, что скажет диктор. Скрипт внизу уже подключён: он ищет элементы по id и переключает aria-expanded.

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

Что было не так раньше

В эпоху jQuery меню делали из div и span с обработчиками кликов, а окна из полупрозрачных слоёв, и всё это хорошо выглядело на картинке. Для диктора такие страницы были набором безымянных блоков, а клавиатурой по ним нельзя было пройти. Появился ARIA, чтобы описать то, чего нет в HTML. Сейчас большинство того, ради чего его придумали, появилось в самом HTML: button, dialog, details, search. Правило осталось прежним: сначала нативный элемент, и лишь потом ARIA.

Практика

Готовлю вашу страницу…

Тест

Вопрос 1 из 6

Какой элемент получит фокус клавишей Tab и нажмётся по Enter без единой строки скрипта?

Один ответ

Карточки

Эти карточки попадут в повторение, когда вы завершите урок.

  • Что слышит человек с диктором?

    Ответ

    Не картинку, а дерево доступности: у каждого элемента имя, роль и состояние (например «Меню, кнопка, свёрнуто»). Браузер строит его из разметки.

  • Почему нативные элементы лучше самодельных?

    Ответ

    button, a, input, label и dialog уже получают фокус, управляются клавишами и сообщают роль. У div с onclick этого нет, и ARIA лишь меняет озвучивание, но не добавляет поведения.

  • Что должно делать модальное окно?

    Ответ

    Перенести фокус внутрь, не выпускать Tab наружу, закрываться по Esc, вернуть фокус на кнопку. Нативный dialog с showModal() делает это сам.

  • Как объявить сообщение, не двигая фокус?

    Ответ

    Контейнер с role="status" (вежливо) или role="alert" (срочно) заранее лежит в странице, а потом в него вставляют текст. Диктор прочтёт его сам.

  • Пятиминутная проверка диктором?

    Ответ

    Включить NVDA или VoiceOver. Пройти по заголовкам (клавиша H), областям (D), полям (F). Выполнить главное действие, не глядя в экран: слышно ли, что это и что произошло.

Источники

Дальше

Теперь вы знаете: клавиатура и чтение с экрана: имя, роль, состояние.