Что делает aria-hidden=true с интерактивными элементами на самом деле

Все знают, что нельзя использовать aria-hidden в интерактивных элементах. Но в чём проблема? Я решил выяснить это, чтобы в следующий раз, когда об этом спросят, я мог лучше объяснить.

Совсем недавно пришлось исправить один паттерн в системе дизайна, вызывавший множество ошибок, о которых сообщалось при автоматическом тестировании доступности. А именно — использование aria-hidden="true" для интерактивных элементов (или их предков). Я помнил из своих тренингов и исследований, что такая комбинация плохо сказывается на доступности, поскольку элементы всё равно получают фокус при "табуляции" на них, даже если они намеренно скрыты от дерева доступности.

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

Скринридеры ведут себя по-разному

До тестирования на скринридерах я бы предположил, что элементы с aria-hidden="true" (на их предке или на них самих) будут полностью игнорироваться скринридерами. Я ожидал этого. Затем возникает вопрос: хорошо, а что, если мы используем скринридер и перемещаемся по странице с помощью Tab? Что тогда произойдёт?

Ну, это зависит (почти торговая марка). Опять — зависит от комбинации скринридера и браузера.

Я не тестировал все возможные комбинации и не тестировал разные версии, только последние, которые были под рукой, и вот результаты;

  • NVDA и Chrome — при переходе Tab к интерактивным элементам они объявляются безымянными (то есть объявляются их роли, но не их имена). Такие интерактивные элементы недоступны в списке элементов и других ярлыках, поэтому практически невидимы.
  • Narrator и Chrome vs. Edge — табуляция по элементам работала так же, как и с обычными интерактивными элементами (в основном игнорируя aria-hidden="true"), за исключением того, что Edge объявлял неверную роль для кнопки, но не для ссылки. Элементы не были доступны в ярлыках Narrator.
  • VoiceOver и Safari (iOS) — ничего не было объявлено, и все элементы были недоступны. Даже непосредственный тап по ним не срабатывал. В меню Rotor нет ни единого следа.
  • TalkBack и Chrome (Android) — то же самое, что и с VoiceOver и Safari — ничего не объявлено, нигде нет следов.

Это были лишь возможные варианты, и на самом деле неважно, какие версии использовались, так как в любом случае вы никогда не должны использовать aria-hidden="true" на родителях — или непосредственно на интерактивных элементах. Но я просто хотел проверить, какие последствия это имеет для пользователей скринридеров.

Это действительно выглядит запутанным, и мне кажется, что TalkBack и VoiceOver, полностью игнорирующие интерактивные элементы, жёстко соблюдают спецификацию, в то время как реализация NVDA и Narrator немного более свободна.

Учтите — эти тесты могут стать неактуальными в любой момент, поскольку всё может измениться, особенно для такого сценария, который не следует использовать в реальной жизни. Но я наверняка вспомню об этом эксперименте, когда в следующий раз буду объяснять, почему это плохо, и, надеюсь, вы тоже.

Код, использованный для тестирования:

<section aria-hidden="true">
<h3>parent with aria-hidden with a button and a link</h3>
<button type="button">Test button in a parent</button>
<a href="#">Test link in a parent</a>
</section>

<section>
<h3>Button and link that have aria-hidden attribute</h3>
<button type="button" aria-hidden="true">Independent button with aria-hidden</button>
<a href="#" aria-hidden="true">Independent link with aria-hidden</a>
</section>

Тестовая страница, если хотите опробовать сценарии.

Как решить эту проблему

В идеале следовало бы использовать CSS display:none; или visibility:hidden; или HTML атрибут hidden, но это не вариант, так как хотелось, чтобы содержимое было как бы видно (из-за необходимости анимации).

Я использовал — теперь уже хорошо поддерживаемый — HTML аттрибут inert. Он решает все проблемы, которые не может решить aria-hidden="true";

  • Контент со всеми дочерними элементами, включая интерактивные, по-прежнему отображается и виден.
  • Вы больше не можете перемещаться табом к интерактивным элементам.
  • Контент и интерактивные элементы удаляются из дерева доступности.

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

Заключение — остерегайтесь aria-hidden=true

Я нечасто использую aria-hidden="true", даже для не интерактивных элементов, за исключением случаев, когда имеются дублирующие иконки (иконки, используемые в кнопке или ссылке, где также есть видимый текст). Последнее время я не использую aria-hidden="true" для всего остального. Это может сбивать с толку, когда что-то скрывается для вспомогательных технологий (например, скринридеров), но при этом отображается визуально (некоторые пользователи скринридеров могут видеть экран).

В любом случае не используйте aria-hidden="true" в интерактивных элементах или их родительских элементах — теперь вы знаете, почему (если раньше вы были настроены скептически).

Дополнительные материалы

Предыдущая Статья

Утверждение структуры JSON ответа в Laravel

Следующая Статья

Докеризация приложения Laravel 11