Современные модальные диалоговые окна часто поддерживают "легкое закрытие", позволяя пользователям закрывать диалоговое окно, щелкая или касаясь фона (области за пределами диалогового окна). Атрибут closedby позволяет включить такое поведение без использования пользовательского кода JavaScript.
Реализация
Чтобы включить закрытие по клику вне области:
- Добавьте
closedby="any"в элемент<dialog>. - Откройте диалоговое окно, нажав
dialog.showModal().
Значения атрибута
any– позволяет закрывать окно нажатием на фон, клавишейEscили с помощью инструментов разработчика (например,dialog.close()).closerequest– активирует только запросы на закрытие и механизмы для разработчиков. Это значение по умолчанию для модальных диалоговых окон.none– диалоговое окно можно закрыть только с помощью механизмов разработчика.
Как настроить стиль фона
Когда диалоговое окно открывается как модальное с помощью showModal(), браузер генерирует псевдоэлемент ::backdrop. Этот фон покрывает всю область просмотра и находится непосредственно за диалоговым окном.
/* Style the backdrop to indicate the dialog is modal */
dialog::backdrop {
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(2px); /* Optional: add blur for modern browsers */
}
Пример
<!-- MANDATORY: Use closedby="any" to enable light-dismiss behavior -->
<dialog id="myDialog" closedby="any" aria-labelledby="dialogTitle">
<form method="dialog">
<h2 id="dialogTitle">Feedback</h2>
<p>Click outside this box or press Esc to dismiss.</p>
<button type="submit">Close</button>
</form>
</dialog>
<button onclick="document.getElementById('myDialog').showModal()">Open Dialog</button>
Ограничения и специальные возможности
- ОБЯЗАТЕЛЬНО. Используйте
closedby="any", чтобы включить закрытие по клику вне элемента. - ОБЯЗАТЕЛЬНО. Всегда открывайте модальные диалоговые окна с помощью
showModal(). Это гарантирует, что диалоговое окно находится на верхнем уровне, фокус захвачен и клавишаEscобрабатывается. - Рекомендуется использовать атрибут
aria-labelledbyилиaria-label, чтобы указать доступное название диалогового окна. - НЕ ИСПОЛЬЗУЙТЕ
closedbyдля немодальных диалоговых окон (открываемых с помощьюshow()), поскольку у них нет фона и они не будут закрываться при нажатии за их пределами. - НЕ используйте событие
clickдля критически важной логики, которая должна выполняться до закрытия. Вместо этого отслеживайте событияcloseилиcancel.
Резервные стратегии
ОБЯЗАТЕЛЬНО. Для браузеров, которые пока не поддерживают closedby, вы должны реализовать резервный вариант закрытия диалогового окна при нажатии за его пределами. Для этого используйте следующий скрипт:
const dialog = document.querySelector('dialog');
// Fallback for browsers without closedby support
if (!('closedBy' in HTMLDialogElement.prototype)) {
dialog.addEventListener('click', (event) => {
// 1. When clicking the backdrop, the event target is the dialog element itself.
// Ignore clicks where the target is a child element inside the dialog.
if (event.target !== dialog) return;
// 2. Check if the click coordinates fall within the dialog's content box.
// This distinguishes between a click on the backdrop vs a click on the dialog's background/padding.
const rect = dialog.getBoundingClientRect();
const isDialogContent = (
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width
);
if (isDialogContent) return;
// 3. Since the click was outside the content area (on the backdrop), manually close the dialog.
dialog.close();
});
}