Модальные диалоговые окна — все еще один из самых проблемных компонентов пользовательского интерфейса. Отбросим тот факт, что сайты часто ими злоупотребляют, прерывая текущие действия пользователей (просить меня подписаться на вашу рассылку, пока я еще не дочитал статью, совсем не круто). Но даже правильно используемые модальные окна часто не учитывают требования доступности.

На данный момент существует очень много готовых решений диалоговых сценариев. Растет осведомленность об элементе dialog. Но проблем и у нативных, и у пользовательских модальных окон (ARIA) все еще хватает.

dialog, чего ждем?

С момента самой первой реализации элемента dialog в Chrome Canary прошло уже почти 5 лет, но он по-прежнему до конца не реализован.

На данный момент ситуация такая:

  • Chrome 37+ и другие браузеры на основе blink поддерживают dialog (Opera 24+, Opera Mobile 46, Android / Chrome android 67).
  • В Firefox (53+) еще требуется разрешение для использования.
  • Safari (macOs и iOS) не поддерживают элемент, хотя запрос на включение висит с 2012 года
  • В Microsoft Edge элемент имеет пометку «рассматривается».
  • Наконец, Internet Explorer никогда не будет поддерживать dialog.

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

Как должен вести себя модальный диалог

Модальный диалог

  1. Когда модальное диалоговое окно активировано, фокус должен быть перемещен на него. Куда именно зависит от содержимого, но обязательно на окно. Это обеспечивает предсказуемый пользовательский интерфейс.
  2. Модальное диалоговое окно должно иметь понятное имя и предоставлять стандартные методы закрытия (кнопка закрытия, нажатие клавиши esc, щелчок мыши или нажатие за пределами окна) и обеспечивать стандартное поведение других команд (например, клавиша F6 по-прежнему должна перемещать фокус клавиатуры в адресную строку браузера).
  3. Пока модальное диалоговое окно активно, скрытое им содержимое должно быть недоступно для пользователей. Клавиша TAB и виртуальный курсор программы чтения с экрана (клавиши со стрелками) не должны покидать диалог и перемещаться по содержимому вне его.
  4. Когда модальное диалоговое окно закрывается, фокус должен вернуться к элементу управления, который первоначально активировал диалоговое окно. Это позволит пользователям продолжать анализировать документ с того места, на котором они остановились. Если модальное диалоговое окно не было инициировано целенаправленным действием пользователя или элемент, который его активировал, больше не находится в DOM, то закрытие должно поместить фокус в логичное место. Например, если диалог был открыт при загрузке страницы, то фокус можно было поместить либо на ее тело, либо на главный элемент. Если триггер был удален из DOM, то идеально разместить фокус как можно ближе к тому месту, где он был.

Обновления ARIA и использование inert

В ARIA 1.1 был добавлен атрибут aria-model и значение dialog для aria-haspopup. Эти дополнения стали бы огромным подспорьем в создании доступных модальных диалогов более доступными, если бы не некоторые моменты реализации.

aria-modal

aria-modal указывает скринридерам, что пользователю должен быть доступен только контент, содержащийся в диалоговом окне с атрибутом aria-modal= "true".

Это очень приятное дополнение к спецификации. aria-modal помогает устранить одно из самых больших препятствий в работе с  модальными окнами: удерживание программы чтения в активном диалоге. Один лишь JavaScript не способен управлять виртуальным курсором.

Практически во всех сочетаниях программ экранного чтения и браузеров этот атрибут работает, как надо, за одним неудачным исключением. Safari + VoiceOver как на macOS, так и на iOS имеют проблемы с доступностью статического содержимого в модальном окне недоступным (см. зарегистрированную ошибку WebKit).

Кроме того, не всегда работает aria-modal="false". Но эта проблема гораздо менее серьезна, так как значение false можно просто не использовать.

aria-haspopup

На момент написания этой статьи большинство программ чтения с экрана еще не поддерживают aria-haspopup="dialog". Часто они не упоминают о связи элемента управления с диалоговым окном, а некоторые вовсе считают, что это открывающееся меню (поскольку haspopup изначально был связан с меню), что приводит к неожиданному пользовательскому опыту.

До тех пор, пока поддержка значения dialog не реализована должным образом, лучше не использовать aria-haspopup на элементе, который открывает модальное окно. В то же время можно добавить какой-то визуальный и/или скрытый индикатор (значок и/или текст).

inert + aria-hidden= true

Чтобы фокус клавиатуры и виртуальный курсор скринридера не взаимодействовали с контентом при открытом модальном окне, можно использовать атрибут inert (полифилл Google и WICG) в паре с aria-hidden="true".

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

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

Наконец, использование aria-hidden= "true" и inert вместе не дает пользователям VoiceOver покинуть модальный диалог при чтении построчно (с помощью клавиш со стрелками вверх и вниз, без клавиши-модификатора VO). Большинство пользовательских модальных окон не учитывают такую навигацию.

Подводные камни

Помимо вышеупомянутых проблем с aria-modal и aria-haspopup= "dialog", есть еще несколько, которые следует отметить:

Не используйте display: none для диалогов

В iOS Safari + VoiceOver, если для элемента изначально установлено свойство display: none, то программа не будет фокусироваться на нем, даже если установить фокус из скрипта. Для обхода этой ошибки следует использовать visibility: hidden для неактивного состояния и visibility: visible для отображения диалога. Поскольку модальное окно в большинстве случаев имеет position: fixed (или absolute), оно не будет занимать физическое пространство в потоке DOM-элементов, visibility можно использовать без опасения.

При использовании атрибута hidden для скрытия модальных окон по умолчанию (это гарантирует, что если CSS вдруг отвалится, диалоги не станут видимыми), можно изменить CSS следующим образом:


display: block отменяет дефолтное значение none, а visibility: hidden скрывает диалог более выгодным способом.

Чрезмерно подробные объявления NVDA

При тестировании с NVDA установка фокуса на не фокусируемый элемент (например, заголовок с tabindex="-1") может привести к многократному объявлению этого элемента и содержимого диалогового окна.

Установка фокуса на первый фокусируемый элемент модального окна может привести к несогласованности и плохому пользовательскому опыту (например, если первый фокусируемый элемент — это кнопка «закрыть» в конце объемного диалога, или поле ввода в середине, то предшествующий контент может быть упущен). Лучше просто сфокусироваться на самом диалоговом окне и позволить пользователю ориентироваться самому.

В IE11 заголовок модального окна должен быть его первым элементом

Первым элементом диалога должен быть заголовок (с доступным именем). Это необходимо для связки Internet Explorer 11 + JAWS. Установка фокуса на окно приведет к объявлению его имени и роли, а затем JAWS повторно объявит имя и роль первого дочернего элемента.

Например, если заголовок диалогового окна предоставляет его имя, то JAWS + IE11 объявит текст заголовка, диалог. текст заголовка, уровень заголовка #. Однако, если первым идет другой элемент, например, кнопка с текстом «закрыть», он будет объявлен как: текст заголовка, диалоговое окно. текст заголовка, кнопка.

NVDA не объявляет роль диалогового окна, когда оно получает фокус

NVDA не объявляет роль диалогового окна, если фокус установлен на сам элемент окна. Например, в NVDA + IE11 будет объявлено только имя. В связке с Firefox или Chrome будет объявлено имя диалога, а затем его содержимое.

Выводы

Пока нативный dialog не приживется во всех основных браузерах, мы будем продолжать нуждаться в ARIA, чтобы убедиться в доступности модальных окон. Но некоторые функции ARIA также относительно новые и требуют некоторого времени для полноценного внедрения.

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

Браузеры, скринридеры и даже рекомендации по созданию / спецификации могут кардинально изменяться со временем. Таким образом, имеет смысл регулярно изучать их.

0 комментариев

Оставить комментарий

*Доступные HTML-теги: a, abbr, blockquote, code, pre, del, i, em, strong, b, strike
*Не будет опубликован