Реализация ARIA-атрибутов для доступности сайта

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация ARIA-атрибутов для доступности сайта
Средняя
~2-3 рабочих дня
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация ARIA-атрибутов для доступности сайта

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

Первое правило ARIA

Не использовать ARIA, если можно обойтись нативным HTML. Нативные элементы уже имеют встроенную доступность:

<!-- Плохо — ARIA-костыли на div -->
<div role="button" tabindex="0" aria-pressed="false">Переключить</div>

<!-- Хорошо — нативный button -->
<button type="button">Переключить</button>

<!-- Плохо -->
<div role="heading" aria-level="2">Заголовок</div>

<!-- Хорошо -->
<h2>Заголовок</h2>

Ключевые ARIA-атрибуты

Роли (roles):

<div role="alert">Ошибка при сохранении</div>           <!-- важное сообщение -->
<div role="status">Сохранено успешно</div>              <!-- некритичное уведомление -->
<nav role="navigation" aria-label="Основная">...</nav>  <!-- навигационный блок -->
<div role="dialog" aria-modal="true">...</div>          <!-- модальное окно -->
<ul role="listbox">...</ul>                              <!-- список выбора -->

Состояния:

<button aria-expanded="false" aria-controls="dropdown-menu">Меню</button>
<ul id="dropdown-menu" aria-hidden="true">...</ul>

<input type="checkbox" aria-checked="mixed">   <!-- промежуточное состояние -->
<button aria-pressed="true">Жирный</button>   <!-- toggle-кнопка -->
<input aria-disabled="true">                  <!-- визуально отключено -->
<div aria-busy="true">Загрузка...</div>

Связи между элементами:

<!-- aria-labelledby — заголовок элемента -->
<section aria-labelledby="section-title">
    <h2 id="section-title">О компании</h2>
</section>

<!-- aria-describedby — дополнительное описание -->
<input id="password" type="password"
       aria-describedby="password-requirements">
<p id="password-requirements">Минимум 8 символов, одна цифра</p>

<!-- aria-controls — управляет другим элементом -->
<button aria-controls="panel-1" aria-expanded="false">Показать детали</button>

<!-- aria-owns — элементы, не являющиеся потомками в DOM -->
<ul role="listbox" aria-owns="option-1 option-2">...</ul>

Живые регионы (Live Regions)

<!-- Автоматически объявляется screen reader при изменении -->
<div aria-live="polite" aria-atomic="true">
    <!-- Вежливо: объявить после текущей речи -->
    Корзина обновлена: 3 товара
</div>

<div aria-live="assertive">
    <!-- Немедленно прервать текущую речь — только для критических ошибок -->
    Ошибка: не удалось подключиться к серверу
</div>

<!-- role="status" = aria-live="polite" + aria-atomic="true" -->
<p role="status">Изменения сохранены</p>

<!-- role="alert" = aria-live="assertive" -->
<p role="alert">Форма содержит ошибки</p>

Компонент уведомлений с ARIA

function NotificationSystem() {
    const [notifications, setNotifications] = useState<Notification[]>([]);

    return (
        <>
            {/* Регион для screen reader — всегда в DOM */}
            <div
                aria-live="polite"
                aria-atomic="false"
                className="sr-only"
                id="sr-notifications"
            >
                {notifications.map(n => (
                    <p key={n.id}>{n.message}</p>
                ))}
            </div>

            {/* Визуальные уведомления */}
            <div className="toast-container">
                {notifications.map(n => (
                    <Toast key={n.id} notification={n} />
                ))}
            </div>
        </>
    );
}

Аккордеон

function Accordion({ items }) {
    const [openIndex, setOpenIndex] = useState<number | null>(null);

    return (
        <div>
            {items.map((item, i) => (
                <div key={item.id}>
                    <h3>
                        <button
                            aria-expanded={openIndex === i}
                            aria-controls={`panel-${i}`}
                            id={`header-${i}`}
                            onClick={() => setOpenIndex(openIndex === i ? null : i)}
                        >
                            {item.title}
                        </button>
                    </h3>
                    <div
                        id={`panel-${i}`}
                        role="region"
                        aria-labelledby={`header-${i}`}
                        hidden={openIndex !== i}
                    >
                        {item.content}
                    </div>
                </div>
            ))}
        </div>
    );
}

Таблицы данных

<table>
    <caption>Статистика продаж за Q3 2024</caption>
    <thead>
        <tr>
            <th scope="col">Продукт</th>
            <th scope="col">Продажи</th>
            <th scope="col">Изменение</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <th scope="row">Продукт A</th>
            <td>1 240</td>
            <td>
                <span aria-label="рост на 12%">+12%</span>
            </td>
        </tr>
    </tbody>
</table>

Частые ошибки

  • aria-hidden="true" на интерактивных элементах — они становятся недоступны с клавиатуры
  • Дублирование нативной семантики: <button role="button"> — избыточно
  • aria-label на несемантических div без role — не работает
  • Динамическое обновление aria-label без aria-live — screen reader не заметит

Срок реализации

Добавление ARIA на кастомные компоненты в существующем проекте: 2–4 дня в зависимости от количества компонентов.