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

Источник: «What does aria-hidden=true actually do to interactive elements?»
Все знают, что нельзя использовать aria-hidden в интерактивных элементах. Но в чём проблема? Я решил выяснить это, чтобы в следующий раз, когда об этом спросят, я мог лучше объяснить.

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

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

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

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

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

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

Это были лишь возможные варианты, и на самом деле неважно, какие версии использовались, так как в любом случае вы никогда не должны использовать 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