По данным отчёта WebAIM Million 2026 на 46.3% сайтов встречаются пустые ссылки и на 30.6% сайтов — пустые кнопки. Обе эти проблемы входят в топ 6 самых частых нарушений доступности, обнаруживаемых с помощью WAVE.
Пустые кнопки и ссылки — это те, у которых имя не задано ни одним из способов и браузер вычисляет его как пустую строку. Вспомогательные технологии используют имя для идентификации элементов, а люди полагаются на это при взаимодействии.
- Программы чтения с экрана озвучивают тип элемента и его имя: «Каталог, ссылка» или «Добавить в корзину, кнопка». Пользователь слышит и понимает, что за элемент и что он делает;
- Программы голосового управления ищут элементы по имени: «Нажми Каталог» или «Нажми Добавить в корзину» программа найдёт элемент на экране и нажмёт на него;
- Программы чтения с экрана и специальные браузерные расширения выводят все ссылки или кнопки со страницы в виде списка, имя используется при формировании этого списка.
При отсутствии имени элементы будут анонимными. Просто какая-то «Ссылка» или «Кнопка». Не понятно назначение, сложно идентифицировать, не удобно взаимодействовать. Всё это создаёт препятствия для пользователей.
Чаще всего пустые ссылки и кнопки получаются, когда они отображаются в виде иконок: три горизонтальные линии, тележка, крестик, урна, стрелка, плюс и так далее. Визуально может быть понятно, но программно — нет.
<button type="button">
<svg>
<!-- иконка с тремя линиями -->
</svg>
</button>
<a
href="/cart"
class="icon icon--cart"
>
<!-- иконка тележки в CSS -->
</a>
<button type="button">
<i class="fa-solid fa-trash">
<!-- иконка мусорки из шрифта -->
</i>
</button>
<a href="/catalog?page=3">
<!-- внешняя иконка стрелки -->
<img
src="/assets/arrow-left.svg"
alt=""
>
</a>
Это примеры «пустых» кнопок и ссылок без имени. Базовое правило таково: у кнопок и ссылок должно быть короткое, лаконичное и понятное имя, заданное одним из способов:
- атрибут
aria-labelledby;- атрибут
aria-label;- элемент
<label> (только для <button>);- текстовый контент;
- атрибут
title.Порядок указывает приоритет применения.
aria-label переопределяет имя, заданное через <label>, а aria-labelledby, в свою очередь, переопределяет имя, заданное в aria-label. Стоит выбрать какой-то один способ и не смешивать во избежание неожиданностей.Наилучшим из способов будет видимый текстовый контент. Он соответствует первому правилу ARIA: не полагаться на атрибуты ARIA и использовать встроенные способы. Также видимый текст можно прочесть в отличие от скрытого.
То есть кнопка или ссылка с иконкой и текстом — лучшее из возможных решений. Глядя на текст становится понятно, что нужно сказать для активации элемента голосом. Также люди с когнитивными нарушениями могут не понимать метафору иконки.
<button type="button">
<svg aria-hidden="true">
<!-- иконка с тремя линиями -->
</svg>
Меню
</button>
<a
href="/cart"
class="icon icon--cart"
>
<!-- иконка тележки в CSS -->
Корзина
</a>
<label for="delete">
Удалить
</label>
<button type="button" id="delete">
<i
class="fa-solid fa-trash"
aria-hidden="true"
>
<!-- иконка мусорки из шрифта -->
</i>
</button>
<a href="/catalog?page=3">
<!-- внешняя иконка стрелки -->
<img
src="/assets/arrow-left.svg"
alt=""
>
Предыдущая страница
</a>
При наличии видимого текста стоит скрыть иконки, если они выполняют только функцию визуальной подсказки и текст уже описывает это. Подойдёт атрибут
aria-hidden="true" или пустой alt="" у <img>, что скрывает элементы из дерева доступности.Видимый контент это хорошо, но не всегда возможно, потому что часто дизайнеры против лишнего визуального шума и загромождения интерфейса, особенно на мобильных. Поэтому распространены именно ссылки и кнопки только с иконками.
В таком случае придётся прибегнуть к скрытым подписям, которые задают имя, но не видны в интерфейсе. Если следовать всё тому же правилу ARIA, то есть несколько способов задать скрытое имя без использования атрибутов ARIA:
- Элемент
<title> внутри <svg> задаёт альтернативный текст для изображения-иконки (работает как alt у <img>) и используется как текстовый контент для вычисления имени;- Специальный класс
visually-hidden делает элемент визуально невидимым, но всё ещё доступным как текстовый контент, который задаёт имя;- Атрибут
title задаёт имя элементу при отсутствии контента, но текст в атрибуте отображается в виде системной всплывающей подсказки только при наведении (и при фокусе в Edge);- Атрибут
alt задаёт альтернативный текст для изображения и его значение также используется как текстовый контент и задаёт имя элементу.Элемент
<title> и атрибут title создают системные всплывающие подсказки. C ними много проблем: появляются только при наведении мыши, не реагируют на настройки размера текста и так далее. Не рекомендуется их использовать.<button type="button">
<svg>
<title>
Меню
</title>
<!-- иконка с тремя линиями -->
</svg>
</button>
<a
href="/cart"
class="icon icon--cart"
>
<!-- иконка тележки в CSS -->
<span class="visually-hidden">
Корзина
</span>
</a>
<button
type="button"
title="Удалить"
>
<i class="fa-solid fa-trash">
<!-- иконка мусорки из шрифта -->
</i>
</button>
<a href="/catalog?page=3">
<!-- внешняя иконка стрелки -->
<img
src="/assets/arrow-left.svg"
alt="Предыдущая страница"
>
</a>
Если прибегнуть к ARIA, то имя кнопок и ссылок можно задать с помощью атрибутов
aria-label или aria-labelledby. Можно указать как на самих элементах, так и на иконках в виде альтернативного текста, который будет использован как текстовый контент кнопки.<button type="button">
<svg
role="img"
aria-label="Меню"
>
<!-- иконка с тремя линиями -->
</svg>
</button>
<a
href="/cart"
class="icon icon--cart"
aria-labelledby="cart-label"
>
<!-- иконка тележки в CSS -->
<span id="cart-label" hidden>
Корзина
</span>
</a>
<span id="del-icon" hidden>
Удалить
</span>
<button type="button">
<i
class="fa-solid fa-trash"
role="img"
aria-labelledby="del-icon"
>
<!-- иконка мусорки из шрифта -->
</i>
</button>
<a
href="/catalog?page=3"
aria-label="Предыдущая страница"
>
<!-- внешняя иконка стрелки -->
<img
src="/assets/arrow-left.svg"
alt=""
>
</a>
- role="img" превращает <svg> в <img>, а aria-label в таком случае работает как alt. Альтернативный текст используется как имя элемента;-
aria-labelledby ссылается на элемент по указанному id и текст этого элемента используется как имя, при этом сам элемент может быть скрыт;-
aria-labelledby также работает как alt для элементов с role="img" и берёт альтернативный текст из указанного элемента;- самый простой и короткий способ — просто указать ссылке или кнопке атрибут
aria-label, который задаёт имя элементу.Какой бы способ вы ни выбрали, всегда проверяйте значение Name у элемента на панели Accessibility в DevTools и проходитесь программой чтения с экрана. Не лишним будет прогнать страницу через Axe и подключить линтеры.
#html #a11y