Dev Tools & Workflow

Руководство для разработчиков по ARIA-меткам, которые действительно помогают

ARIA-метки — не магический слой доступности. При грамотном использовании они делают элементы управления понятными. При небрежном — скрывают полезный текст и создают запутанные интерфейсы.

The Wux Webtools Team The Wux Webtools Team 1 минуты чтения С поддержкой ИИ, проверено человеком
Illustration of a developer reviewing accessible labels and UI components on a screen.
Содержание
  1. ARIA-метки нужны для имён, а не для извинений
  2. Доступное имя простыми словами
  3. Первое правило: предпочитайте нативный HTML и видимые подписи
  4. Когда `aria-label` — правильный инструмент
  5. Когда `aria-label` — неправильный инструмент
  6. Используйте `aria-labelledby`, когда видимый текст уже существует
  7. Используйте `aria-describedby` для справочного текста, а не для имени
  8. Повторяющимся элементам управления нужны уникальные имена
  9. Не размечайте метками всё подряд
  10. Проверяйте вычисленное имя, а не только код
  11. Практический чеклист для проверки
  12. Спокойная дисциплина хорошей ARIA

ARIA-метки нужны для имён, а не для извинений

ARIA полезна, но её часто используют как заплатку для неясного HTML. Именно здесь команды начинают сталкиваться с проблемами.

Самый частый пример — aria-label. На вид всё безобидно: добавить строку, удовлетворить линтер, двигаться дальше. Но доступное имя — не украшение. Это имя, которое многие вспомогательные технологии показывают или озвучивают пользователям, когда они перемещаются по кнопкам, ссылкам, полям форм, заголовкам, ориентирам и элементам управления.

Если это имя расплывчатое, продублированное, устаревшее или отличается от видимой подписи, интерфейс становится сложнее использовать. Иногда хуже: aria-label может переопределить более хороший текст, который уже был в DOM.

Цель не в том, чтобы добавить больше ARIA. Цель — сделать имя, роль, состояние и назначение каждого элемента интерфейса понятными.

Доступное имя простыми словами

У большинства интерактивных элементов есть доступное имя. Скринридеры используют это имя, чтобы сообщить, что представляет собой элемент.

Например:

<button>Save changes</button>

Скринридер может объявить что-то вроде: “Save changes, button.” Роль берётся из нативного элемента button. Имя берётся из текста внутри него.

Это идеальный случай: видимый текст и доступное имя совпадают.

Атрибуты ARIA для разметки имён становятся полезны, когда видимый интерфейс не даёт полного имени или когда имя должно браться из другого элемента. Основные атрибуты:

  • aria-label: задаёт строку прямо на элементе.
  • aria-labelledby: указывает на один или несколько элементов, чей текст становится именем.
  • aria-describedby: указывает на вспомогательный текст описания, а не на основное имя.

Эти три атрибута связаны между собой, но не взаимозаменяемы.

Первое правило: предпочитайте нативный HTML и видимые подписи

Если можно разместить видимый текст на элементе управления, сначала сделайте это.

Так лучше:

<button>Delete invoice</button>

Чем так:

<button aria-label="Delete invoice">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

Второй паттерн допустим для кнопки только с иконкой. Но если дизайн может выдержать видимый текст, он помогает всем: пользователям скринридеров, пользователям голосового ввода, людям с когнитивной нагрузкой, тем, кто быстро просматривает страницу, и тем, кто использует инструменты перевода.

Это повторяющаяся тема в работе над доступностью. Нативный HTML и видимые подсказки решают больше проблем, чем скрытые метаданные. Тот же принцип шире применим и к семантике кнопок; если ваша команда проводит аудит элементов управления UI, наш чеклист по доступным веб-кнопкам хорошо дополнит это руководство.

Когда aria-label — правильный инструмент

Используйте aria-label, когда элементу нужно доступное имя и нет подходящего видимого текста, на который можно сослаться.

Классический случай — кнопка только с иконкой:

<button aria-label="Search">
  <svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">
    <!-- icon -->
  </svg>
</button>

Это разумно. Видимая иконка подсказывает поиск, но сам SVG-путь не даёт надёжного имени. aria-label его предоставляет.

Другие хорошие случаи:

  • Кнопка закрытия, представленная только “X”.
  • Навигационный ориентир, которому нужно более конкретное имя, например aria-label="Product".
  • Повторяющийся элемент управления, где видимый контекст не является частью текста кнопки.

Например:

<nav aria-label="Primary">
  ...
</nav>

<nav aria-label="Footer">
  ...
</nav>

Оба являются навигационными ориентирами, но их метки помогают пользователям различать их при перемещении по ориентирам.

Когда aria-label — неправильный инструмент

Не добавляйте aria-label только потому, что тест сообщает: элементу нужна подпись. Сначала исправьте разметку.

Плохо:

<div role="button" tabindex="0" aria-label="Submit">Submit</div>

Лучше:

<button>Submit</button>

Первый пример создаёт лишнюю работу. Теперь вам нужно заново реализовать поведение клавиатуры, отключённые состояния, поведение формы и ожидания, которые нативные кнопки уже обеспечивают.

Также избегайте использования aria-label, чтобы переименовать видимый текст так, что меняется смысл.

<button aria-label="Delete invoice">Remove</button>

Это выглядит незначительно, но может запутать пользователей, которые полагаются на голосовой ввод. Если на видимой кнопке написано “Remove”, а её доступное имя — “Delete invoice”, пользователь, пытающийся сказать “click Remove”, может не получить ожидаемый результат. Требование WCAG “label in name” существует именно по этой причине: видимый текст в целом должен содержаться в доступном имени.

Более удачная версия:

<button aria-label="Remove invoice">Remove</button>

Часто ещё лучше:

<button>Remove invoice</button>

Используйте aria-labelledby, когда видимый текст уже существует

Если текст подписи уже есть на странице, aria-labelledby обычно лучше, чем aria-label.

Пример:

<h2 id="billing-title">Billing address</h2>
<section aria-labelledby="billing-title">
  ...
</section>

Доступное имя секции теперь берётся из видимого заголовка. Вы избегаете дублирования строк, что снижает риск ошибок перевода и устаревших меток.

Это особенно полезно для групп полей формы:

<fieldset aria-labelledby="shipping-speed-title">
  <legend id="shipping-speed-title">Shipping speed</legend>

  <label>
    <input type="radio" name="shipping" value="standard">
    Standard
  </label>

  <label>
    <input type="radio" name="shipping" value="express">
    Express
  </label>
</fieldset>

Во многих случаях нативного legend достаточно без ARIA. Суть в том, что видимые подписи должны быть первичными. ARIA должна связывать уже существующий смысл, а не создавать его вторую приватную версию.

Используйте aria-describedby для справочного текста, а не для имени

Описание — это не подпись.

Рассмотрим это поле:

<label for="password">Password</label>
<input id="password" type="password" aria-describedby="password-help">
<p id="password-help">Use at least 12 characters.</p>

Доступное имя — “Password.” Описание — “Use at least 12 characters.” Скринридер может объявить и то и другое, но они служат разным целям.

Не делайте так:

<input type="password" aria-label="Use at least 12 characters">

Так поле получает имя по инструкции, а не по понятию. Пользователь, перемещающийся по форме, сначала хочет знать, что это за поле, а затем — какие ограничения к нему применяются.

Это различие важно и в состояниях ошибки:

<label for="email">Email</label>
<input
  id="email"
  type="email"
  aria-invalid="true"
  aria-describedby="email-error"
>
<p id="email-error">Enter an email address in the format [email protected].</p>

Подпись остаётся стабильной. Сообщение об ошибке становится вспомогательным контекстом.

Повторяющимся элементам управления нужны уникальные имена

Списки и карточки — места, где ARIA-метки часто становятся необходимыми.

Плохо:

<button>Delete</button>
<button>Delete</button>
<button>Delete</button>

Пользователь скринридера, перемещаясь по кнопкам, может услышать “Delete, button” три раза без какого-либо контекста.

Хорошо:

<button aria-label="Delete report: Q4 revenue">Delete</button>
<button aria-label="Delete report: Hiring plan">Delete</button>
<button aria-label="Delete report: Vendor list">Delete</button>

Это корректное использование aria-label: видимый текст остаётся кратким, а доступное имя включает объект.

Но используйте этот паттерн осторожно. Если имя объекта видно рядом, aria-labelledby может быть более удобным для поддержки:

<article>
  <h3 id="report-q4">Q4 revenue</h3>
  <button aria-labelledby="delete-q4 report-q4" id="delete-q4">Delete</button>
</article>

Доступное имя становится “Delete Q4 revenue.” Это позволяет не дублировать заголовок отчёта в атрибуте.

Не размечайте метками всё подряд

Не каждому элементу нужна ARIA-метка.

Статическому тексту обычно не нужна. Декоративным иконкам — тоже. Контейнерам — тоже, если только у них нет осмысленной роли ориентира или виджета. Избыточные метки могут сделать страницу шумной и более сложной для навигации.

Для изображений используйте модель, специфичную для изображений: содержательным изображениям нужен полезный alt; декоративным изображениям нужен пустой alt="". Не используйте ARIA-метки как замену хорошему тексту для изображений. Если ваша команда смешивает эти понятия, вернитесь к прагматичному alt-тексту для изображений и отделите альтернативы для изображений от имён элементов управления.

Распространённая ошибка — давать каждому SVG aria-label. Если SVG находится внутри кнопки, а у кнопки уже есть имя, иконку обычно следует скрыть от вспомогательных технологий:

<button aria-label="Open menu">
  <svg aria-hidden="true" focusable="false">...</svg>
</button>

Иначе пользователь может услышать избыточные или странные объявления в зависимости от сочетания браузера и вспомогательной технологии.

Проверяйте вычисленное имя, а не только код

Ошибки доступности часто переживают code review, потому что разметка выглядит правдоподобно.

Современные инструменты разработчика в браузерах могут показывать вычисленное дерево доступности. В Chrome, Edge, Firefox и Safari проинспектируйте элемент и найдите информацию о доступности, такую как роль, имя и описание. Вы проверяете три вещи:

  1. Роль такая, как вы ожидаете?
  2. Доступное имя ясное и конкретное?
  3. Описание полезно, но не заменяет имя?

Затем протестируйте несколько сценариев с реальным скринридером. Вам не нужно становиться штатным экспертом по вспомогательным технологиям, чтобы поймать базовые проблемы. В macOS VoiceOver встроен. В Windows широко используется и бесплатно доступен NVDA. На мобильных устройствах, где это релевантно, тестируйте с VoiceOver на iOS и TalkBack на Android.

Автоматизированные инструменты полезны, но они не могут надёжно определить, достаточно ли контекстны “Open,” “Read more,” или “Delete”. Относитесь к автоматизации как к сети, а не как к судье. Это похоже на аудит производительности: отчёт может указать на подозрительные области, но вам всё равно нужно интерпретировать влияние. Здесь применим тот же спокойный подход, который мы рекомендуем при чтении отчёта Lighthouse без паники.

Практический чеклист для проверки

Перед выпуском ARIA-меток спросите:

  • Можно ли вместо этого использовать нативный HTML?
  • Есть ли видимый текст, который следует использовать как подпись?
  • Если видимый текст существует, включает ли доступное имя этот текст?
  • Уникальны ли повторяющиеся элементы управления, когда по ним перемещаются вне визуального контекста?
  • Подключён ли справочный текст через aria-describedby, а не принудительно встроен в подпись?
  • Скрыты ли декоративные иконки от вспомогательных технологий?
  • Проверил ли кто-то вычисленное доступное имя в инструментах разработчика браузера?
  • Был ли выполнен хотя бы один проход критического сценария с реальным скринридером?

Этот чеклист помогает поймать большинство проблем с метками до того, как они станут проблемами пользователей.

Спокойная дисциплина хорошей ARIA

Хорошая работа с ARIA редко выглядит драматично. В основном это сдержанность.

Используйте настоящие кнопки. Используйте настоящие подписи. Согласовывайте видимые и доступные имена. Добавляйте aria-label только тогда, когда нет лучшего видимого источника. Используйте aria-labelledby, когда на странице уже есть нужный текст. Используйте aria-describedby для вспомогательных инструкций и ошибок.

Веб-платформа многое даёт разработчикам бесплатно, когда мы используем её напрямую. ARIA существует для пробелов. Навык — понять, когда пробел действительно есть.

Часто задаваемые вопросы

Должна ли у каждой кнопки быть aria-label?
Нет. Кнопка с понятным видимым текстом обычно уже имеет хорошее доступное имя. Добавляйте `aria-label` только когда видимый текст отсутствует или недостаточен, например у кнопки только с иконкой или у повторяющейся кнопки “Delete”, которой нужен контекст.
В чём разница между aria-label и aria-labelledby?
`aria-label` задаёт текстовую строку прямо в атрибуте. `aria-labelledby` указывает на существующий текст в другом месте страницы. Если подходящий видимый текст уже существует, `aria-labelledby` обычно проще поддерживать.
Может ли aria-label исправить div, используемый как кнопка?
Он может дать элементу имя, но не заставит его вести себя как настоящая кнопка. Вам всё равно нужно будет обработать поведение клавиатуры, фокус, состояния и ожидаемую семантику. В большинстве случаев используйте нативный `<button>`.
Должен ли aria-label точно совпадать с видимым текстом?
Обычно он должен включать видимый текст, особенно для интерактивных элементов управления. Это помогает пользователям голосового ввода и соответствует намерению рекомендаций WCAG по label-in-name.
Как узнать, что объявит скринридер?
Начните с проверки дерева доступности в инструментах разработчика браузера: посмотрите роль, имя и описание. Затем протестируйте критические взаимодействия с реальным скринридером, таким как VoiceOver, NVDA, TalkBack или JAWS.

Источники и дальнейшее чтение

  1. WAI-ARIA Authoring Practices Guide
  2. MDN: aria-label attribute
  3. Accessible Name and Description Computation 1.2
  4. WCAG 2.2 Success Criterion 2.5.3: Label in Name
Об авторе
The Wux Webtools Team

Последнее обновление:

Продолжайте читать

Dev Tools & Workflow

Почему автоматическое тестирование доступности пропускает половину ваших проблем

Автоматические инструменты доступности находят очевидные дефекты, а не реальные проблемы пользовательского опыта. Вот где они дают сбой и как проверить остальное.

1 минуты чтения