В этом посте я хочу поделиться с сообществом модальным диалогом, который я реализовал с помощью HTML, CSS и JavaScript, который удовлетворяет тестам, установленным рабочей группой W3C WCAG:

  1. Убедитесь, что role = dialog является атрибутом контейнера (например, div), который используется в качестве настраиваемого диалогового окна.
  2. Убедитесь, что контейнер вставлен (или сделан видимым) с помощью JavaScript после взаимодействия с пользователем или какого-либо другого события.
  3. Когда диалоговое окно активировано, убедитесь, что фокус установлен на элемент в контейнере.
  4. Когда диалог активен, убедитесь, что фокус никогда не устанавливается на элемент, которого нет в контейнере.
  5. Когда диалоговое окно деактивировано, убедитесь, что фокус установлен на элемент управления, который изначально активировал диалоговое окно.

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

  • Модальный диалог закрывается, когда пользователь нажимает Escape.
  • Модальный диалог закрывается, когда пользователь щелкает мышью за пределами его видимой части.

HTML-код

В приведенном выше HTML-коде наиболее подходящими строками являются:

Строка 12: мы устанавливаем для атрибута aria-haspopup значение dialog в теге body. Я также подумал о том, чтобы установить его на alerttdialog, но я подумал, что это всплывающее окно не предназначено для оповещения пользователя, поэтому роль alert кажется менее подходящей для этого случая. Мы устанавливаем этот атрибут, чтобы сообщать программам чтения с экрана, что у основного элемента есть всплывающее окно.

Строки 15–16: это внешний блок модального окна, здесь:
- мы присваиваем атрибуту роль диалог (мог быть alerttdialog ).
- Мы устанавливаем aria-modal в значение true, чтобы указать программам чтения с экрана, что это модальный элемент.
- Мы указываем aria-label В соответствии с требованиями роли диалога.
- Мы установили для aria-live значение assertive, чтобы при обновлении (появлении) диалогового окна программы чтения с экрана немедленно объявляли об этом.

Строки 45–46: импорт необходимых скриптов:
- Код JavaScript для модального окна (см. ниже).
- инертный полифилл, установить все, что находится за модальным окном, как инертный, чтобы оно было недоступно не только для программ чтения с экрана, но и для навигации с клавиатуры.

Код JavaScript

Я попытался написать код, не требующий пояснений, но некоторые части могут потребовать пояснений:

Строка 3: мы сохраняем элемент, у которого есть фокус при открытии модального окна. Это необходимо для того, чтобы вернуть фокус обратно на место, когда пользователь закроет модальное окно (строка 25).

Строка 9: мы хотим закрыть модальное окно, когда пользователь нажимает на «серую» непрозрачную часть (оверлей) вокруг модального окна.

Строка 45: в этом конкретном случае мы могли искать только кнопки. Чтобы сделать код более пригодным для повторного использования, мы также ищем другие элементы, которые могут получать фокус и могут находиться в модальном диалоговом окне. Мы фокусируемся на первом найденном элементе.

Строка 50: это та часть, где нам нужен инертный полифилл.

Таблица стилей CSS

Я думаю, что CSS не требует особого объяснения, но я чувствую, что хочу мотивировать выбор выбора свойства отображения CSS, свойства видимости CSS или скрытого атрибута.

Использование видимости на оверлее потребовало бы (в целях безопасности) установить для видимости значение «наследование» для дочерних элементов, потому что потомки элемента будут видны, если у них есть видимость установлена ​​на visible. Кроме того, если для позиции не задано значение fixed или absolute, элемент все равно будет занимать место, даже если он не отображается. Таким образом, использование свойства display было безопаснее и сэкономило одну строку кода.

Риск, связанный с атрибутом hidden вместо этого, заключается в том, что изменение значения свойства CSS display для элемента с атрибутом hidden переопределяет поведение атрибут скрытый. Поэтому я решил, что будет безопаснее просто использовать свойство CSS display.

При использовании по умолчанию display: none казалось, есть ошибка в iOS Safari + VoiceOver, но публикации, в которой она упоминается, более двух лет, я не смог найти дополнительную информацию о это, и при тестировании я не обнаружил упомянутой ошибки.

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

Если вы нашли этот пост полезным и хотите меня поблагодарить, вы можете купить мне кофе.