Поддержка доступности: ARIA-атрибуты (role, aria-label, aria-describedby и др.)
Почему ARIA — это важно? 🌍
Доступность (a11y) — не просто тренд, а необходимость. Миллионы пользователей с ограниченными возможностями взаимодействуют с веб-сайтами через скринридеры. ARIA (Accessible Rich Internet Applications) — набор атрибутов, которые делают динамический контент понятным для вспомогательных технологий.
Без ARIA:
<div onclick="toggleMenu()">☰</div> <!-- Скринридер увидит просто символ "☰" -->
С ARIA:
<button
aria-label="Открыть меню"
onclick="toggleMenu()"
>☰</button> <!-- Технологии поймут, что это кнопка с действием -->
Основные ARIA-атрибуты 🛠️
role — определяем семантику
Указывает, какой элемент перед нами, если браузер не может определить это сам.
<div role="navigation"> <!-- Явно говорим: это навигация -->
<ul>...</ul>
</div>
📌 Когда использовать:
- Для нестандартных элементов (например, кастомные dropdown-меню).
- Когда нативный HTML-тег не подходит (например, <div> вместо <button>).
aria-label и aria-labelledby — подписи для элементов
Делают непонятный контент осмысленным для скринридеров.
aria-label (если текст короткий):
<button aria-label="Закрыть модальное окно">✖</button>
aria-labelledby (если описание есть в другом элементе):
<h2 id="modal-title">Подтверждение</h2>
<div aria-labelledby="modal-title">...</div>
aria-describedby — дополнительное описание
Полезно для сложных элементов, где нужны пояснения.
<input
type="password"
aria-describedby="hint-password"
>
<p id="hint-password">Пароль должен содержать не менее 8 символов</p>
aria-hidden — скрываем лишнее
Убирает из дерева доступности декоративные элементы (иконки, разделители).
<span aria-hidden="true">※</span> <!-- Скринридер проигнорирует этот символ -->
Практика: делаем доступный аккордеон 🎹
Проблема: Обычный аккордеон на div + JavaScript не передаёт состояние скринридеру.
Решение:
<div
role="button"
aria-expanded="false"
aria-controls="content-1"
onclick="toggleSection()"
>
Раздел 1
</div>
<div id="content-1" aria-hidden="true">
Скрытый контент...
</div>
<script>
function toggleSection() {
const button = document.querySelector('[aria-controls="content-1"]');
const content = document.getElementById('content-1');
const isExpanded = button.getAttribute('aria-expanded') === 'true';
button.setAttribute('aria-expanded', !isExpanded);
content.setAttribute('aria-hidden', isExpanded);
}
</script>
📌 Что мы сделали:
- Добавили
role="button"для семантики. - Использовали
aria-expandedдля отслеживания состояния. - Связали кнопку и контент через
aria-controls.
Ошибки новичков ⚠️
- Дублирование ролей:
<button role="button">Неправильно</button> <!-- role избыточен! -->
- Игнорирование нативных элементов:
<div role="checkbox">...</div> <!-- Лучше использовать <input type="checkbox"> -->
``
3. **Неизменяемые состояния**:
```html
<button aria-expanded="false">Всегда false</button> <!-- Должно меняться динамически! -->
Инструменты для проверки 🛠️
-
Screen Readers:
- NVDA (Windows, бесплатный).
- VoiceOver (macOS, встроенный).
-
DevTools:
- Chrome: вкладка Accessibility в Elements.
- Firefox: Accessibility Inspector.
-
Онлайн-валидаторы:
- WAVE (wave.webaim.org).
Итоги: ключевые принципы ✅
- Используй нативные HTML-элементы (
<button>,<nav>) — они уже доступны. - ARIA — только когда HTML не справляется (кастомные виджеты).
- Тестируй с реальными скринридерами.
- Следи за динамическими изменениями (
aria-expanded,aria-live).
Примеры Данилы Бежина на YouTube: @DanilaBezhin помогут глубже разобраться в теме! 🎥