Поддержка доступности: 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>

📌 Что мы сделали:

  1. Добавили role="button" для семантики.
  2. Использовали aria-expanded для отслеживания состояния.
  3. Связали кнопку и контент через aria-controls.

Ошибки новичков ⚠️

  1. Дублирование ролей:
<button role="button">Неправильно</button> <!-- role избыточен! -->
  1. Игнорирование нативных элементов:
<div role="checkbox">...</div> <!-- Лучше использовать <input type="checkbox"> -->
``

3. **Неизменяемые состояния**:
```html
<button aria-expanded="false">Всегда false</button> <!-- Должно меняться динамически! -->

Инструменты для проверки 🛠️

  1. Screen Readers:

    • NVDA (Windows, бесплатный).
    • VoiceOver (macOS, встроенный).
  2. DevTools:

    • Chrome: вкладка Accessibility в Elements.
    • Firefox: Accessibility Inspector.
  3. Онлайн-валидаторы:

    • WAVE (wave.webaim.org).

Итоги: ключевые принципы ✅

  1. Используй нативные HTML-элементы (<button>, <nav>) — они уже доступны.
  2. ARIA — только когда HTML не справляется (кастомные виджеты).
  3. Тестируй с реальными скринридерами.
  4. Следи за динамическими изменениями (aria-expanded, aria-live).

Примеры Данилы Бежина на YouTube: @DanilaBezhin помогут глубже разобраться в теме! 🎥

Скрыть рекламу навсегда

🧠 Учёба без воды и зубрёжки

Закрытый Boosty с наработками опытного преподавателя.

Объясняю сложное так, чтобы щелкнуло.

🚀 Забрать доступ к Boosty