Атрибут aria-label входит в спецификацию WAI-ARIA – набор атрибутов ARIA, которыми HTML-разметке добавляют семантику для вспомогательных технологий. Его единственная задача – задать элементу доступное имя (accessible name): строку, которую скринридер произнесёт вместо отсутствующего или невнятного текста. Зрячий пользователь видит иконку-крестик и понимает, что кнопка закрывает окно; программа чтения экрана без aria-label объявит только «кнопка», без имени. Это базовый инструмент доступности (a11y) и одновременно самый злоупотребляемый ARIA-атрибут: на аудитах проблемы чаще создаёт не его отсутствие, а избыточное или неправильное применение.
Как это работает
Браузер вычисляет доступное имя каждого элемента по алгоритму accessible name computation и передаёт его вспомогательным технологиям через дерево доступности. Источники имени имеют строгий приоритет: сначала aria-labelledby, затем aria-label, затем нативные механизмы – видимый текст элемента, label у поля формы, alt у изображения, title. Отсюда два следствия. Первое: aria-label перекрывает видимый текст кнопки, alt картинки и подпись инпута – скринридер услышит только его. Второе: если на элементе заданы оба ARIA-атрибута, победит aria-labelledby. Базовый пример – кнопка-иконка без текста:
<button type="button" aria-label="Закрыть">
<svg aria-hidden="true" focusable="false">…</svg>
</button>Второй нюанс – aria-label работает не везде. Спецификация запрещает именование для ролей generic (обычные div и span без role), paragraph, code, emphasis, strong, time и других статических ролей. По тестам скринридеров JAWS и NVDA игнорируют aria-label на статике без роли, VoiceOver и TalkBack озвучивают лишь частично – поведение непредсказуемо, полагаться на него нельзя. Практическое правило: атрибут надёжен только на интерактивных элементах, виджетах, лендмарках, изображениях и iframe.
Когда подходящий текст уже есть в разметке, вместо невидимой строки на него ссылаются через aria-labelledby:
<h2 id="billing">Платёжные данные</h2>
<form aria-labelledby="billing">…</form>Такое имя обновится вместе с заголовком и корректно переведётся автопереводчиком – закрыты сразу два слабых места aria-label, о которых ниже.
aria-label, aria-labelledby, alt и title – в чём разница
| Атрибут | Как задаёт имя | Когда использовать |
|---|---|---|
| aria-label | Невидимая строка прямо в атрибуте; перекрывает видимый текст, alt и title | Видимого текста нет: кнопки-иконки, поле поиска, лендмарки |
| aria-labelledby | Ссылка по id на видимый текст; имя обновляется вместе с ним; приоритет выше aria-label | Подходящий текст уже есть в разметке: заголовок секции, подпись |
| alt | Нативное доступное имя изображения | Всегда для содержательных img – ARIA не нужен |
| title | Тултип; низший приоритет, недоступен с клавиатуры и на тачскринах | Как источник имени не полагаться |
Зачем это нужно
Легитимных сценариев немного: кнопки и ссылки, где вместо текста иконка (бургер, крестик, лупа, корзина); различение одинаковых лендмарков, когда на странице два nav – основное меню и хлебные крошки; iframe со сторонним виджетом. Во всех остальных случаях сначала пробуют нативную разметку: в иерархии способов именования aria-label стоит последним. Три антипаттерна, которые встречаются чаще всего:
- aria-label на div и span – роль generic запрещает именование, скринридеры атрибут игнорируют или ведут себя по-разному. Типичный случай из вёрстки магазинов:
<span aria-label="Скидка">-20%</span>– не работает. - Перекрытие видимого текста – нарушение критерия WCAG 2.5.3 Label in Name. Если у кнопки с текстом «Отправить» стоит
aria-label="submit-form", пользователь голосового управления скомандует «нажать Отправить» – и команда не сработает, потому что доступное имя другое. Правило: доступное имя обязано содержать видимый текст, лучше в начале строки. - Ставка на автоперевод – сервис Google Translate не переводит aria-label вовсе, а встроенные переводчики Chrome, Edge и Firefox переводят нестабильно: пропускают скрытые (display:none) и динамически подставленные значения. Тесты Адриана Розелли, обновлённые в июле 2025, подтверждают: полагаться на автоперевод aria-label нельзя. Для мультиязычных сайтов – видимый текст или aria-labelledby.
Для инструкций и подсказок aria-label тоже не подходит: пояснение вроде «пароль не короче 12 символов» должно быть видимым текстом, связанным через aria-describedby, – инструкции нужны всем пользователям, а не только скринридерам. Есть и смежный эффект: корректные доступные имена делают разметку понятнее не только вспомогательным технологиям, но и парсерам поисковиков и LLM, которые восстанавливают структуру страницы для ответов, – это часть базовой гигиены GEO.
Пример
Типовая задача на Битрикс-проектах – шапка интернет-магазина: три кнопки-иконки (поиск, избранное, корзина) и бургер мобильного меню. Без ARIA скринридер объявит четыре безымянные кнопки подряд. Исправленная разметка:
<button type="button" aria-label="Поиск по сайту">
<svg aria-hidden="true">…</svg>
</button>
<button type="button" aria-label="Избранное">
<svg aria-hidden="true">…</svg>
</button>
<a href="/cart/" aria-label="Корзина, 3 товара">
<svg aria-hidden="true">…</svg>
</a>
<button type="button" aria-label="Открыть меню" aria-expanded="false">
<svg aria-hidden="true">…</svg>
</button>Иконки закрыты aria-hidden="true", чтобы SVG не озвучивался отдельно, а состояние бургера дополнительно сообщает атрибут aria-expanded. Активный пункт меню, к которому ведёт бургер, помечают атрибутом aria-current. А вот кнопке «Оформить заказ» с нормальным текстом aria-label не нужен вовсе: текст уже является доступным именем, и лишний атрибут только создаст риск расхождения между тем, что видит зрячий пользователь, и тем, что слышит пользователь скринридера.