Почему toast не отображается поверх dialog и как это исправить
Разработчики часто сталкиваются с ситуацией, когда всплывающие уведомления (toast) перестают быть видны после внедрения модальных окон через элемент <dialog>. Это связано с тем, что <dialog> помещается в top-layer - специальный слой браузера, который находится выше всех обычных элементов, включая ваши кастомные плашки.
Причина: top-layer и z-index
Элемент <dialog> с атрибутом open или после вызова .showModal() автоматически попадает в top-layer. Этот слой не подчиняется правилам z-index и всегда отрисовывается поверх остального контента. Даже если задать toast огромный z-index: 99999, он останется под диалогом, потому что top-layer физически выше в стеке отрисовки.
Рабочие решения
1. Помещение toast внутрь dialog (с управлением жизненным циклом)
Этот вариант предложил ИИ. Суть: при открытии диалога вы переносите узел toast внутрь <dialog> через appendChild, а при закрытии - возвращаете обратно в родительский контейнер. Недостаток: нужно следить за событиями открытия/закрытия и корректно восстанавливать позиционирование.
// Пример на JavaScript
const dialog = document.querySelector('dialog');
const toast = document.querySelector('.toast');
dialog.addEventListener('close', () => {
document.body.appendChild(toast);
});
dialog.addEventListener('open', () => {
dialog.appendChild(toast);
});
2. Отказ от dialog в пользу кастомного модального окна
Если вы не привязаны к семантике <dialog>, проще всего реализовать модальное окно на <div> с управлением z-index. В этом случае toast будет просто иметь больший z-index, чем модалка, и проблема исчезнет. Недостаток: потеря нативной доступности (ARIA-атрибуты и управление фокусом придётся добавлять вручную).
3. Использование Popover API (если допустим современный браузер)
Popover API (свойство popover) также работает через top-layer, но поддерживается с 2024-2025 года. Для вас этот вариант не подходит, так как моральная отсечка - 2022 год.
Рекомендация
Для проектов с поддержкой браузеров с 2022 года лучше всего подходит первый вариант (перенос toast внутрь dialog) или полный отказ от <dialog> в пользу кастомного решения. Если вы выберете кастомное модальное окно, не забудьте добавить:
- Атрибут
role="dialog"иaria-modal="true" - Обработку фокуса (ловушка фокуса внутри модалки)
- Закрытие по клавише Escape
Таким образом, вы получите полный контроль над z-index и сможете легко управлять видимостью toast-уведомлений.