ARIA-атрибуты: когда и как их использовать
Практика3 минРедакция Innovialabs
Коротко
ARIA сообщает вспомогательным технологиям роль, имя и состояние элемента, но не добавляет поведения; используйте её только там, где нет подходящего нативного HTML-элемента.
Что такое ARIA и главное правило
ARIA (Accessible Rich Internet Applications) — набор HTML-атрибутов, которые объясняют экранным дикторам, что за элемент перед ними и в каком он состоянии. ARIA меняет только то, как элемент описывается в дереве доступности. Она не добавляет поведения: не делает элемент фокусируемым и не обрабатывает клавиши.
Первое правило ARIA: если есть нативный HTML-элемент с нужной семантикой и поведением — используйте его, а не ARIA.
<!-- Плохо: нужно вручную добавлять tabindex, Enter, пробел -->
<div role="button" onclick="save()">Сохранить</div>
<!-- Хорошо: всё уже встроено -->
<button type="button" onclick="save()">Сохранить</button>
Неправильная ARIA хуже, чем её отсутствие: она может сообщить диктору неверную информацию.
Три вида атрибутов
| Вид | Что описывает | Примеры |
|---|---|---|
| Роли (roles) | Чем является элемент | role="dialog", role="tab", role="alert" |
| Свойства (properties) | Постоянные характеристики и связи | aria-label, aria-labelledby, aria-describedby, aria-controls |
| Состояния (states) | То, что меняется при взаимодействии | aria-expanded, aria-selected, aria-checked, aria-hidden |
Состояния нужно обновлять из JavaScript при каждом изменении интерфейса — иначе диктор будет сообщать устаревшие данные.
Самые полезные атрибуты
aria-label— даёт имя элементу без видимого текста, например кнопке с иконкой.aria-labelledby— берёт имя из другого элемента поid, например заголовок модального окна.aria-describedby— добавляет пояснение: подсказку или текст ошибки.aria-expanded— раскрыт ли связанный блок: аккордеон, выпадающее меню.aria-hidden="true"— скрывает элемент от диктора. Никогда не ставьте его на фокусируемые элементы.aria-current="page"— отмечает текущую страницу в навигации.
Паттерн: модальное окно
Сегодня проще всего взять нативный <dialog> и открывать его через showModal(): браузер сам делает фон неактивным и закрывает окно по Esc.
<dialog aria-labelledby="dlg-title">
<h2 id="dlg-title">Удалить проект?</h2>
<p>Действие нельзя отменить.</p>
<button type="button">Отмена</button>
<button type="button">Удалить</button>
</dialog>
Если окно своё, на div: role="dialog", aria-modal="true", aria-labelledby, перевод фокуса внутрь при открытии, удержание фокуса, закрытие по Esc и возврат фокуса на кнопку-открыватель.
Паттерн: вкладки
<div role="tablist" aria-label="Тарифы">
<button role="tab" id="t1" aria-selected="true" aria-controls="p1">Месяц</button>
<button role="tab" id="t2" aria-selected="false" aria-controls="p2" tabindex="-1">Год</button>
</div>
<div role="tabpanel" id="p1" aria-labelledby="t1">…</div>
<div role="tabpanel" id="p2" aria-labelledby="t2" hidden>…</div>
Поведение с клавиатуры: Tab переводит фокус на активную вкладку и дальше в панель, стрелки переключают вкладки. При переключении обновляйте aria-selected и tabindex.
Паттерн: меню и выпадающие списки
Частая ошибка — ставить role="menu" на обычную навигацию сайта. Роль menu предназначена для меню приложения в стиле десктопных программ и требует управления стрелками. Для навигации и простого раскрывающегося списка ссылок достаточно:
<button type="button" aria-expanded="false" aria-controls="nav-list">Услуги</button>
<ul id="nav-list" hidden>
<li><a href="/web">Сайты</a></li>
<li><a href="/mobile">Приложения</a></li>
</ul>
При открытии меняйте aria-expanded на true и убирайте hidden.
Паттерн: live-регионы
Live-регион сообщает диктору об изменениях, которые происходят без перехода фокуса: «Товар добавлен в корзину», «Сохранено», ошибки отправки формы.
<div aria-live="polite" id="status"></div>
aria-live="polite"— диктор дочитает текущую фразу и затем озвучит изменение. Подходит почти всегда.role="alert"(соответствуетassertive) — прерывает речь. Только для срочных ошибок.- Регион должен существовать в DOM заранее, а меняться должен его текст. Элемент, добавленный вместе с текстом, часто не озвучивается.
Частые ошибки
aria-labelнаdivилиspanбез роли — многие дикторы его игнорируют.aria-hidden="true"на контейнере, внутри которого есть кнопки.- Роль без поведения:
role="button"без обработки клавиш. - Состояния не обновляются:
aria-expanded="false"у открытого меню. - Дублирование:
<button aria-label="Кнопка Отправить">Отправить</button>— имя должно совпадать с видимым текстом.
Полные паттерны с клавиатурным поведением описаны в ARIA Authoring Practices Guide.