Семантика и ARIA
Что это такое
Всё, что встречает ассистивная технология, она описывает тремя вещами: ролью элемента, его доступным именем и состоянием. Откуда браузер берёт эти значения — вопрос семантики: у button роль «button», и он получает фокус; имя input даёт связанный с ним label; чекбокс сообщает, отмечен он или нет. А ARIA — набор атрибутов, которые переопределяют или дополняют сказанное разметкой; он нужен там, где ни один нативный элемент не подходит.
Почему это важно
Элемент управления без имени объявляется как «button», и пользователь не понимает, что перед ним. Состояние, переданное только цветом — красная рамка, серая строка, — для того, кто слушает, а не смотрит, не существует. И это не редкие случаи: так описан интерфейс для другого чувства. Зато сама правка по большей части не требует ничего, кроме сдержанности: правильная ARIA — обычно никакой ARIA, ведь нативный элемент уже несёт нужную роль, имя и поведение с клавиатуры, а написанному вручную заменителю приходится воспроизводить все три правильно.
Ключевые идеи
Сначала нативный элемент
<button>, <a href>, <input type="checkbox">, <select> и <details> приходят с уже реализованными ролями, поведением с клавиатуры, обработкой фокуса и участием в форме. Воспроизвести что-либо из этого через div и ARIA возможно и почти всегда хуже: атрибуты ARIA описывают элемент управления, но не заставляют его работать.
<!-- объявляется как «Подписаться, button» и работает с клавиатуры -->
<button type="button">Подписаться</button>
Каждому элементу управления нужно доступное имя
Имя берётся из содержимого элемента, связанного label или, когда ни то ни другое невозможно, из aria-label / aria-labelledby. Иконки — частая ошибка: у кнопки, единственный потомок которой — иконка SVG, нет текста, поэтому иконку нужно скрыть от дерева, а кнопке дать имя.
<button type="button" aria-label="Закрыть диалог">
<svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">…</svg>
</button>
ARIA — для пробелов, а не для украшения
aria-hidden="true" убирает элемент из дерева доступности — полезно для декоративной иконки, разрушительно для фокусируемого элемента управления. role заменяет роль элемента, и к нему стоит прибегать только для виджетов, у которых действительно нет HTML-эквивалента, например списка вкладок или live-региона.
Объявляйте изменения, которые происходят без перехода
Регион, который обновляется без загрузки страницы — фильтр поиска, подтверждение сохранения, — зрячий пользователь увидит, а все остальные нет. Чтобы новое содержимое было объявлено, пока пользователь не занят, на регионе ставят aria-live="polite"; пользуйтесь этим умеренно и делайте объявления короткими.
<p role="status" aria-live="polite">{message}</p>
Не передавайте смысл только цветом
Обязательные поля, ошибки, выбранные строки и статусы нужны со второй подсказкой: текстом, иконкой, подчёркиванием, узором рамки. Это же исправление работает и для людей с дальтонизмом, и для всех, кто читает с выцветшего экрана при дневном свете.
Практика
Дайте имя каждому элементу управления на странице
Откройте страницу, которую сопровождаете, перечислите все интерактивные элементы и выпишите доступное имя, которое скринридер объявил бы для каждого. Сверьте ответы с деревом доступности в браузере.
Готово, когда: ни один элемент управления не объявляется без имени, и у каждой кнопки-иконки есть либо видимая подпись, либо aria-label, называющий действие.
Замените кликабельный div на нужный элемент
Найдите div с обработчиком onClick, решите, ведёт он куда-то или совершает действие, и используйте a или button, сохранив оформление.
Готово, когда: элемент достигается клавишей Tab, активируется Enter и Space там, где это уместно, а дерево доступности сообщает соответствующую роль.
Частые ошибки
aria-hidden="true"на фокусируемом элементе — он остаётся в порядке табуляции, но у него нет имени, и пользователь с клавиатуры попадает в тишину; исправить: скрывайте только декоративное содержимое, а элементу управления дайте собственное имя.- Кнопка, собранная из
divсrole="button"— Enter и Space её не активируют, и форма никогда не отправляется; исправить: используйте настоящийbuttonи оформите его. - Placeholder как единственная подпись — имя исчезает при вводе и объявляется ненадёжно; исправить: добавьте
label, связанный черезforиid. - Молчание при изменении содержимого — фильтр, который обновляется без объявления, выглядит для пользователя скринридера сломанным; исправить: пометьте регион
aria-live="polite"и держите сообщение коротким. - Ошибка, переданная только красной рамкой — ошибка невидима для всех, кто не различает цвет; исправить: добавьте текстовое сообщение, связанное с полем, и иконку или префикс как вторую подсказку.
Что читать дальше
- Язык гипертекстовой разметки (HTML) (02-frontend/03-html) — семантика, на которой строится этот урок; выбранный элемент задаёт роль, которую слышит пользователь.
- Клавиатурный доступ и фокус (02-frontend/11-accessibility-wcag-a11y/02-keyboard-and-focus) — вторая половина той же гарантии.
- Figma (программа для дизайна) (03-design-ux/12-figma) — место, где решения о цвете и контрасте часто принимаются задолго до появления разметки.