Диалог

Элемент dialog — полезный элемент для представления любого типа диалога в HTML. Узнайте, как он работает.

Модальное диалоговое окно — это особый тип всплывающего окна на веб-странице, которое отвлекает пользователя от просмотра, позволяя ему сосредоточиться на самом себе. Существуют некоторые обоснованные примеры использования всплывающего диалогового окна , но перед этим следует тщательно всё обдумать. Модальные диалоговые окна заставляют пользователей сосредоточиться на определённом контенте и, по крайней мере временно, игнорировать остальную часть страницы.

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

Семантический HTML-элемент <dialog> для создания диалогового окна включает в себя семантику, взаимодействие с клавиатурой и все свойства и методы интерфейса HTMLDialogElement .

Вот пример модального элемента <dialog> . Откройте диалоговое окно кнопкой «Открыть модальное диалоговое окно». После открытия диалоговое окно можно закрыть тремя способами: нажатием клавиши ESC, отправкой формы с помощью кнопки с установленным атрибутом formmethod="dialog" (или если сама форма имеет method="dialog" ) и методом HTMLDialogElement.close() .

HTMLDialogElement имеет три основных метода, а также все методы, унаследованные от HTMLElement .

dialog.show() /* opens the dialog */
dialog.showModal() /* opens the dialog as a modal */
dialog.close() /* closes the dialog */

Поскольку этот <dialog> был открыт с помощью метода HTMLDialogElement.showModal() , он является модальным диалоговым окном. Открытие модального диалогового окна деактивирует и скрывает всё, кроме самого диалогового окна. Если навести указатель мыши на пользовательский интерфейс за пределами диалогового окна, вы заметите, что все элементы ведут себя так, как будто установлено pointer-events: none; даже кнопка, открывающая диалоговое окно, не реагирует на взаимодействие.

При открытии диалогового окна фокус перемещается в него. Фокус устанавливается на первом элементе в порядке последовательной навигации с помощью клавиатуры внутри этого диалогового окна. При повторном нажатии клавиши tab фокус может получить только содержимое внутри диалогового окна, пока оно открыто. Всё, что находится за пределами модального окна, остаётся инертным, пока оно открыто.

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

Существует глобальный атрибут inert , который можно использовать для отключения элемента и всех его потомков, за исключением любого активного диалогового окна. При открытии модального диалогового окна с помощью showModal() он становится инертным или деактивированным; этот атрибут явно не задаётся.

Фон, скрывающий всё, кроме диалогового окна, можно стилизовать с помощью псевдоэлемента ::backdrop . Фон отображается только при отображении элемента <dialog> с помощью метода .showModal() . Этот псевдоэлемент соответствует всем фонам, включая тот, который отображается при использовании FullScreen API , например, при просмотре видео в полноэкранном режиме, соотношение сторон которого отличается от соотношения сторон экрана или монитора.

Немодальные диалоги

HTMLDialogElement.show() аналогичным образом открывает диалоговое окно, но без добавления фона и без приостановки работы. Клавиша Esc не закрывает немодальные диалоговые окна. В связи с этим ещё важнее включить метод закрытия немодального диалогового окна. При этом, если закрывающий элемент находится за пределами диалогового окна, фокус будет переключён на элемент, открывший диалоговое окно, что может быть не самым удобным для пользователя.

Хотя кнопка закрытия диалогового окна официально не требуется спецификацией, считайте её обязательной. Клавиша ESC закроет модальное диалоговое окно, но не немодальное. Видимая кнопка, способная получать фокус, улучшает доступность и пользовательский опыт.

Закрытие диалога

Для закрытия диалогового окна метод HTMLDialogElement.close() не нужен. JavaScript вообще не нужен. Чтобы закрыть <dialog> без JavaScript, добавьте форму с методом dialog, установив method="dialog" для <form> или formmethod="dialog" для кнопки.

При отправке формы пользователем с помощью метода dialog состояние введённых пользователем данных сохраняется. Пока происходит событие отправки (форма проходит проверку ограничений) (если не задано novalidate ), данные пользователя не очищаются и не отправляются. Кнопку закрытия без JavaScript можно написать так:

<dialog open>
  <form method="dialog">
    <button type="submit" autofocus>close</button>
  </form>
</dialog>

Вы, возможно, заметили, что в этом примере для кнопки закрытия <button> установлен атрибут autofocus . Элементы с атрибутом autofocus , установленным внутри элемента <dialog> , не получат фокус при загрузке страницы (если только страница не загружена с видимым диалоговым окном). Однако они получат фокус при открытии диалогового окна.

По умолчанию при открытии диалогового окна фокус будет получен первым фокусируемым элементом в нём, если только атрибут autofocus не установлен для другого элемента в диалоговом окне. Установка атрибута autofocus для кнопки закрытия гарантирует, что она получит фокус при открытии диалогового окна. Однако включение autofocus в тег <dialog> следует выполнять с большой осторожностью. Все элементы в последовательности, предшествующие элементу с автофокусировкой, пропускаются. Мы рассмотрим этот атрибут подробнее в уроке, посвящённом фокусировке .

Интерфейс HTMLDialogElement включает свойство returnValue . Отправка формы с помощью method="dialog" устанавливает returnValue равным name кнопки отправки (если таковое имеется), используемой для отправки формы. Если бы мы написали <button type="submit" name="toasty">close</button> , returnValue было бы toasty .

При открытии диалогового окна присутствует логический атрибут open , что означает, что диалоговое окно активно и с ним можно взаимодействовать. Если диалоговое окно открывается добавлением атрибута open , а не с помощью .show() или .showModal() , оно будет немодальным. Свойство HTMLDialogElement.open возвращает значение true или false в зависимости от того, доступно ли диалоговое окно для взаимодействия, а не от того, является ли оно модальным.

Хотя JavaScript является предпочтительным методом открытия диалогового окна, включение атрибута open при загрузке страницы и его последующее удаление с помощью .close() может помочь гарантировать доступность диалогового окна, даже если JavaScript недоступен.

Дополнительные детали

Не используйте tabindex

Элемент, активируемый для открытия диалогового окна, и содержащаяся в нём кнопка закрытия (и, возможно, другой контент) могут получать фокус и являются интерактивными. Элемент <dialog> не является интерактивным и не получает фокус. Не добавляйте свойство tabindex к самому диалоговому окну.

Роли ARIA

Неявная роль — dialog . Если диалоговое окно представляет собой окно подтверждения, передающее важное сообщение, требующее подтверждения или другого ответа пользователя, установите role="alertdialog" . Диалоговое окно также должно иметь доступное имя. Если видимый текст может предоставить доступное имя, добавьте aria-labelledby="idOfLabelingText" .

CSS по умолчанию

Обратите внимание, что браузеры предоставляют стили по умолчанию для dialog . Firefox, Chrome и Edge устанавливают color: CanvasText; background-color: Canvas; а Safari устанавливает color: black; background-color: white; в своих таблицах стилей user-agent. color наследуется от dialog , а не от body или :root , что может быть неожиданно. Свойство background-color не наследуется.

Проверьте свое понимание

Проверьте свои знания элемента диалога.

Как оформить область за диалоговым окном?

С псевдоэлементом ::background .
Попробуйте еще раз.
С псевдоэлементом ::backdrop .
Правильный!
Со свойством background .
Попробуйте еще раз.