Что такое ARIA-атрибуты и для чего они нужны?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое ARIA-атрибуты и для чего они нужны
ARIA (Accessible Rich Internet Applications) — это набор атрибутов HTML, которые помогают сделать веб-приложения доступными для пользователей с ограниченными возможностями, особенно для людей, которые используют скрин-ридеры (программы для чтения с экрана).
Что такое ARIA
ARIA атрибуты добавляют дополнительную информацию о роли, состоянии и свойствах элементов HTML. Они помогают вспомогательным технологиям (screen readers, voice control и т.д.) лучше понять структуру и функционал страницы.
<!-- Без ARIA (неясно что это) -->
<div onclick="deleteItem()">X</div>
<!-- С ARIA (очень понятно) -->
<button aria-label="Delete item">X</button>
<!-- Или с дополнительной информацией -->
<div role="button" aria-label="Close" tabindex="0">X</div>
Основные типы ARIA атрибутов
1. role — определяет роль элемента
<!-- Элемент действует как кнопка -->
<div role="button" onclick="submit()">Submit</div>
<!-- Элемент — список -->
<div role="list">
<div role="listitem">Item 1</div>
<div role="listitem">Item 2</div>
</div>
<!-- Элемент — навигация -->
<div role="navigation">
<a href="/">Home</a>
<a href="/about">About</a>
</div>
<!-- Alert, dialog, tab, alertdialog и т.д. -->
2. aria-label — текстовое описание элемента
<!-- Иконка без текста нуждается в описании -->
<button aria-label="Search">
<svg class="icon">...</svg>
</button>
<!-- Для скрин-ридера звучит как "Search button" -->
<!-- Интерактивный элемент без видимого текста -->
<div aria-label="Close menu" class="close-btn">×</div>
3. aria-labelledby — связь с элементом, содержащим текст
<!-- Заголовок модального окна -->
<h2 id="modal-title">Confirm action</h2>
<!-- Модальное окно связано с заголовком -->
<div role="dialog" aria-labelledby="modal-title">
<p>Are you sure?</p>
<button>Yes</button>
<button>No</button>
</div>
4. aria-describedby — дополнительное описание
<!-- Поле формы с ошибкой -->
<input
type="email"
aria-describedby="email-error"
value="invalid-email"
/>
<span id="email-error" role="alert">
Please enter valid email
</span>
5. aria-hidden — скрывает элемент от скрин-ридера
<!-- Декоративные иконки скрыты от скрин-ридера -->
<span aria-hidden="true">→</span>
<!-- Но видимы для зрячих пользователей -->
<span>Next page</span>
<!-- Полезно для скрытых меню и элементов -->
<div aria-hidden="true" class="decorative-bg"></div>
State атрибуты
<!-- aria-checked — состояние чекбокса -->
<div role="checkbox" aria-checked="false">
I agree to terms
</div>
<!-- aria-expanded — раскрыто/закрыто -->
<button aria-expanded="false" aria-controls="menu">
Menu
</button>
<div id="menu" hidden>
<a href="/">Home</a>
<a href="/about">About</a>
</div>
<!-- aria-disabled — отключено/включено -->
<button aria-disabled="false">Submit</button>
<!-- aria-selected — выбрано/не выбрано -->
<div role="tab" aria-selected="true">Tab 1</div>
<!-- aria-busy — идет загрузка -->
<div aria-busy="true" aria-label="Loading data">
<span class="spinner"></span>
</div>
Live regions — динамическое содержимое
<!-- Скрин-ридер уведомит об изменениях -->
<div aria-live="polite">
Loading...
</div>
<!-- aria-live="assertive" для важных сообщений -->
<div aria-live="assertive" role="alert">
Critical error occurred!
</div>
<!-- aria-atomic="true" читает весь регион -->
<div aria-live="polite" aria-atomic="true">
Showing 1-10 of 100 results
</div>
Практические примеры
Пример 1: Custom кнопка вместо div
<!-- Плохо: div не имеет семантики -->
<div onclick="deleteUser()">Delete</div>
<!-- Хорошо: button уже имеет семантику -->
<button onclick="deleteUser()">Delete</button>
<!-- Если очень нужен div (редко) -->
<div
role="button"
tabindex="0"
aria-label="Delete user"
onclick="deleteUser()"
onkeydown="handleKeydown(event)"
>
Delete
</div>
Пример 2: Иконка с текстом/описанием
<!-- Неправильно: только иконка -->
<button>
<svg class="search-icon">...</svg>
</button>
<!-- Правильно: добавляем aria-label -->
<button aria-label="Search">
<svg class="search-icon" aria-hidden="true">...</svg>
</button>
<!-- Или через aria-labelledby -->
<button>
<svg class="search-icon" aria-hidden="true">...</svg>
<span id="search-text">Search</span>
</button>
Пример 3: Выпадающее меню
<button
aria-expanded="false"
aria-controls="menu"
id="menu-button"
>
Menu
</button>
<div id="menu" hidden aria-labelledby="menu-button">
<a href="/">Home</a>
<a href="/about">About</a>
<a href="/contact">Contact</a>
</div>
<script>
const button = document.getElementById('menu-button');
const menu = document.getElementById('menu');
button.addEventListener('click', () => {
const isExpanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', !isExpanded);
menu.hidden = isExpanded;
});
</script>
Пример 4: Форма с валидацией
<form>
<div>
<label for="email">Email</label>
<input
id="email"
type="email"
aria-describedby="email-hint email-error"
required
/>
<span id="email-hint" class="hint">
Enter valid email (example@mail.com)
</span>
<span id="email-error" role="alert" aria-live="polite">
<!-- Ошибка будет добавлена JavaScript -->
</span>
</div>
<button type="submit">Submit</button>
</form>
Пример 5: Modal диалог
<div
role="dialog"
aria-labelledby="dialog-title"
aria-describedby="dialog-content"
aria-modal="true"
>
<h2 id="dialog-title">Confirm deletion</h2>
<p id="dialog-content">
This action cannot be undone
</p>
<button>Cancel</button>
<button>Delete</button>
</div>
React компоненты с ARIA
interface ButtonProps {
onClick: () => void;
ariaLabel?: string;
ariaDescribedBy?: string;
disabled?: boolean;
}
function CustomButton({
onClick,
ariaLabel,
ariaDescribedBy,
disabled,
children
}: ButtonProps) {
return (
<button
onClick={onClick}
aria-label={ariaLabel}
aria-describedby={ariaDescribedBy}
disabled={disabled}
>
{children}
</button>
);
}
// Использование
<CustomButton
ariaLabel="Close modal"
onClick={() => closeModal()}
>
×
</CustomButton>
Чеклист для accessibility
Обязательные ARIA атрибуты:
- Все кнопки имеют aria-label или видимый текст
- Иконки имеют aria-hidden="true"
- Форма имеет связанные label элементы
- Ошибки имеют role="alert"
- Динамическое содержимое имеет aria-live
- Modal окна имеют role="dialog" и aria-modal="true"
- Все интерактивные элементы могут быть активированы клавиатурой (tabindex, Enter, Space)
Что НЕ нужно делать
<!-- Плохо: aria-label на div вместо button -->
<div aria-label="Submit" onclick="submit()">Send</div>
<!-- Хорошо: используй семантические элементы -->
<button onclick="submit()">Send</button>
<!-- Плохо: aria-label на элемент с видимым текстом -->
<button aria-label="Click me">Click me</button>
<!-- Хорошо: aria-label только если нужно дополнительное описание -->
<button>Click me</button>
<!-- Плохо: aria-hidden на интерактивные элементы -->
<button aria-hidden="true">Click me</button>
<!-- Хорошо: aria-hidden только на декоративные элементы -->
<span aria-hidden="true">→</span>
Инструменты для тестирования
# axe DevTools браузер расширение
# Проверяет доступность страницы автоматически
# NVDA (для Windows) или VoiceOver (для Mac)
# Скрин-ридеры для тестирования в реальности
# Lighthouse в DevTools
# Встроенная проверка доступности
Заключение
ARIA атрибуты нужны для:
- Помощи скрин-ридерам понять структуру страницы
- Описания пользовательских компонентов
- Передачи состояния элементов
- Информирования об ошибках и обновлениях
- Навигации по сложным интерфейсам
Первое правило ARIA: если можно использовать HTML элемент (button, nav, main), используй его вместо ARIA. ARIA — это для сложных случаев, когда HTML недостаточно.
Использование ARIA делает ваше приложение доступным для миллионов людей с ограниченными возможностями.