ARIA атрибуты

ARIA (Accessible Rich Internet Applications) представляет собой набор специальных атрибутов, расширяющих стандартную семантику HTML и позволяющих улучшить доступность интерфейсов для вспомогательных технологий. Основная цель ARIA заключается в передаче дополнительной информации о состоянии, роли и свойствах интерфейсных элементов, которые невозможно выразить стандартными HTML-средствами.

Ключевая идея использования ARIA состоит в том, что эти атрибуты не заменяют нативную семантику HTML, а дополняют её. Приоритет всегда остаётся за стандартными элементами, такими как <button>, <input>, <nav>, <header>, поскольку они уже обладают встроенной доступностью.

ARIA следует правилу: если можно решить задачу с помощью HTML — ARIA не требуется.


Роли (role) как основа семантики

Атрибут role определяет назначение элемента в структуре интерфейса. Он сообщает вспомогательным технологиям, как именно следует интерпретировать узел DOM.

Основные категории ролей

Структурные роли

  • banner — верхняя часть страницы
  • navigation — навигационный блок
  • main — основной контент
  • contentinfo — футер

Интерактивные роли

  • button — элемент, ведущий себя как кнопка
  • checkbox — переключатель состояния
  • switch — тумблер
  • tab, tabpanel — вкладки интерфейса

Композитные роли

  • listbox — список выбора
  • grid — таблица с интерактивными ячейками
  • tree — древовидная структура

Пример применения:

<div role="button" tabindex="0">
  Отправить
</div>

Однако предпочтительным остаётся использование:

<button>Отправить</button>

Атрибут aria-label и aria-labelledby

aria-label

Используется для задания текстовой подписи, когда визуальный текст отсутствует или недостаточен.

<button aria-label="Закрыть окно">
  ×
</button>

Типичные сценарии:

  • иконки без текста
  • элементы управления с визуальными символами
  • компактные UI-компоненты

aria-labelledby

Связывает элемент с другим элементом, содержащим текстовое описание.

<h2 id="title">Настройки профиля</h2>

<div role="region" aria-labelledby="title">
  ...
</div>

В отличие от aria-label, здесь используется уже существующий текст, что повышает консистентность интерфейса.


Состояния интерфейса (aria-* состояния)

ARIA предоставляет набор атрибутов для описания динамических состояний элементов.

aria-expanded

Отражает раскрытие/сворачивание компонента.

<button aria-expanded="false" aria-controls="menu">
  Меню
</button>

<ul id="menu" hidden>
  <li>Пункт 1</li>
</ul>

При изменении состояния через JavaScript значение обновляется:

button.setAttribute("aria-expanded", "true");
menu.hidden = false;

aria-hidden

Управляет видимостью элемента для вспомогательных технологий.

<div aria-hidden="true">
  Декоративный контент
</div>

Важно: aria-hidden="true" не скрывает элемент визуально.


aria-disabled

Описывает неактивное состояние элемента.

<button aria-disabled="true">Сохранить</button>

В отличие от disabled, не всегда блокирует взаимодействие, поэтому требует дополнительной логики в JavaScript.


aria-checked

Используется для чекбоксов и переключателей.

<div role="checkbox" aria-checked="false" tabindex="0"></div>

Состояния:

  • true
  • false
  • mixed

Динамические обновления: aria-live

Атрибут aria-live определяет, как изменения содержимого будут озвучиваться экранными читалками.

Политики обновления

  • off — обновления игнорируются
  • polite — обновления объявляются после завершения текущей речи
  • assertive — прерывают текущую речь

Пример:

<div aria-live="polite">
  Сообщение отправлено
</div>

Использование в Jav * aScript:

status.textContent = "Файл загружен";

aria-atomic и aria-relevant

aria-atomic

Определяет, должно ли обновление восприниматься как целое.

<div aria-live="polite" aria-atomic="true">
  Прогресс: 70%
</div>

При true экранный чтец озвучивает весь блок целиком.


aria-relevant

Контролирует, какие типы изменений отслеживаются:

  • additions
  • removals
  • text
  • all
<div aria-live="polite" aria-relevant="additions text"></div>

Связывание элементов: aria-controls и aria-describedby

aria-controls

Указывает, каким элементом управляет текущий контрол.

<button aria-controls="sidebar">
  Открыть
</button>

<aside id="sidebar"></aside>

aria-describedby

Добавляет дополнительное описание элемента.

<input aria-describedby="hint">

<span id="hint">Минимум 8 символов</span>

Выделение текущего состояния: aria-current

Используется для обозначения активного элемента в наборе.

<nav>
  <a href="/" aria-current="page">Главная</a>
  <a href="/about">О нас</a>
</nav>

Возможные значения:

  • page
  • step
  • location
  • true

Валидация форм: aria-required и aria-invalid

aria-required

<input type="text" aria-required="true">

aria-invalid

<input type="email" aria-invalid="true">

Используется совместно с визуальной индикацией ошибок и текстовыми сообщениями.


aria-busy

Отражает состояние загрузки или обработки.

<div aria-busy="true">
  Загружается...
</div>

При завершении процесса:

container.setAttribute("aria-busy", "false");

Практика обновления ARIA через JavaScript

ARIA-атрибуты часто изменяются динамически в ответ на действия пользователя.

function toggleMenu() {
  const expanded = button.getAttribute("aria-expanded") === "true";

  button.setAttribute("aria-expanded", String(!expanded));
  menu.hidden = expanded;
}

Обновление состояния должно быть синхронизировано с DOM, иначе возникает рассинхронизация между визуальным интерфейсом и его семантическим представлением.


Распространённые ошибки использования ARIA

Использование ARIA часто приводит к ухудшению доступности при неправильной интеграции.

Подмена нативных элементов

<div role="button"></div>

вместо

<button></button>

Отсутствие управления клавиатурой

ARIA-роль не добавляет интерактивности автоматически.

Несоответствие состояния

<button aria-expanded="true"></button>
<!-- при этом меню скрыто -->

Избыточное применение aria-hidden

Скрытие значимого контента приводит к потере доступности.


Взаимодействие ARIA с JavaScript-интерфейсами

В динамических интерфейсах ARIA становится частью состояния приложения. В компонентах, построенных на чистом JavaScript или фреймворках, состояние UI синхронизируется с набором атрибутов:

  • открытие модальных окон → aria-hidden, aria-modal
  • раскрытие списков → aria-expanded
  • уведомления → aria-live
  • формы → aria-invalid, aria-required

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


Структурирование сложных компонентов

Интерфейсы высокой сложности (таблицы, деревья, вкладки) требуют комбинирования ролей и состояний.

Пример вкладочного интерфейса:

<div role="tablist">
  <button role="tab" aria-selected="true">Вкладка 1</button>
  <button role="tab" aria-selected="false">Вкладка 2</button>
</div>

<div role="tabpanel">Содержимое 1</div>

Синхронизация состояния вкладок должна поддерживать:

  • aria-selected
  • управление фокусом
  • соответствие отображаемой панели

Иерархия доступности и приоритеты

При построении интерфейса учитывается приоритет источников семантики:

  1. Нативный HTML
  2. Семантика ARIA
  3. JavaScript-логика поведения

Несоблюдение этого порядка приводит к конфликтам интерпретации и снижению качества взаимодействия с ассистивными технологиями.