Когда элемент <dialog> открывается как модальное окно с помощью showModal(), браузер перемещает его на верхний слой и помечает остальную часть документа как инертную. Хотя это блокирует клики указателя и фокус клавиатуры на базовой странице, это не предотвращает прокрутку:
- Если пользователь прокручивает страницу, когда указатель или жест касания находится над элементом
::backdrop, то прокручивается страница под ним. - Прокрутка внутри
<dialog>переходит на основную страницу, когда диалоговое окно достигает границы прокрутки, или сразу, если контент диалогового окна не переполнен.
Согласно спецификации CSS Overscroll Behavior, свойство overscroll-behavior применяется ко всем элементам контейнера прокрутки, включая непрокручиваемые контейнеры прокрутки (элементы с overflow: hidden или overflow: auto, содержимое которых в настоящее время не переполняется). Объединив overscroll-behavior: contain в <dialog> с overflow: hidden и overscroll-behavior: contain в dialog::backdrop, вы можете запретить прокрутку основной страницы, используя только CSS.
Реализация
1. Ограничьте цепочку прокрутки в элементе <dialog>
Таблица стилей агента пользователя устанавливает overflow: auto для <dialog>, делая его контейнером прокрутки по умолчанию. Примените overscroll-behavior: contain (или none) к dialog:modal (или dialog).
2. Как превратить ::backdrop в контейнер прокрутки и ограничить прокрутку
По умолчанию для dialog::backdrop задано значение overflow: visible, то есть это не контейнер прокрутки и overscroll-behavior игнорируется. Вам нужно установить overflow: hidden для dialog::backdrop, чтобы сделать его нескроллящимся контейнером прокрутки, и связать его с overscroll-behavior: contain, чтобы жесты прокрутки, выполняемые над фоном, перехватывались и не достигали документа под ним.
Пример кода
dialog:modal {
/* MANDATORY: Prevent scroll gestures inside the modal (even when its content
does not overflow) from chaining to the underlying page. */
overscroll-behavior: contain;
}
dialog::backdrop {
/* MANDATORY: ::backdrop defaults to overflow: visible (not a scroll container).
Set overflow: hidden so it becomes a non-scrollable scroll container that
honors overscroll-behavior. */
overflow: hidden;
overscroll-behavior: contain;
}
Рекомендации и ограничения
- ОБЯЗАТЕЛЬНО. Задайте
overscroll-behavior: containдля самого элемента<dialog>(с помощью селектораdialog:modal) иdialog::backdrop. Без этого объявления жесты прокрутки на фоне или внутри диалогового окна по-прежнему будут привязаны к странице. - ОБЯЗАТЕЛЬНО. Задайте для
overflow: hidden(илиoverflow: auto) значениеdialog::backdrop, чтобы сделать его контейнером прокрутки. Без этой декларации::backdropпо умолчанию принимает значениеoverflow: visible, аoverscroll-behaviorне действует. - НЕ используйте
overflow: clipилиoverflow: visibleнаdialog::backdropилиdialog. Ни одно из значений не создает контейнер прокрутки, поэтомуoverscroll-behaviorне будет применяться. - НЕ применяйте
overflow: hiddenилиposition: fixedк<html>или<body>, чтобы заблокировать прокрутку фона при открытии диалогового окна. Изменение переполнения корневого элемента удаляет полосу прокрутки страницы (что приводит к горизонтальному сдвигу макета), может сбросить или изменить позицию прокрутки страницы и нарушить работу элементовposition: stickyна базовой странице.
Резервные стратегии
Хотя свойство CSS overscroll-behavior поддерживается во всех основных браузерах для контейнеров прокрутки с переполненным контентом, соблюдение overscroll-behavior для непрокручиваемых контейнеров прокрутки – это более новая спецификация, которую невозможно обнаружить.
НЕ пытайтесь определить поддержку нескроллящихся контейнеров с помощью @supports (overscroll-behavior: contain) или CSS.supports('overscroll-behavior', 'contain'). Все современные браузеры поддерживают синтаксис свойства overscroll-behavior: contain и возвращают true, даже если они применяют его только при переполнении контента.
Вместо этого рассматривайте изоляцию прокрутки в непрокручиваемых контейнерах как прогрессивное улучшение:
- В браузерах, поддерживающих
overscroll-behaviorдля нескроллящихся контейнеров, прокрутка фоновой страницы полностью блокируется как надdialog::backdrop, так и внутри<dialog>(независимо от того, переполнен ли его контент). - В браузерах, которые пока не поддерживают
overscroll-behaviorдля непрокручиваемых контейнеров,overscroll-behavior: containдляdialogпо-прежнему предотвращает цепочку прокрутки, когда контент диалогового окна переполняется и его можно прокручивать. При этомshowModal()по-прежнему захватывает фокус клавиатуры и помечает фоновый документ какinert. - Рекомендуется использовать прогрессивное улучшение, а не устаревшие обходные решения, в которых
overflow: hiddenилиposition: fixedприменяется к<html>или<body>, поскольку оно не удаляет корневую полосу прокрутки, не вызывает горизонтальные сдвиги макета, не приводит к переходу к позиции прокрутки страницы и не нарушает работу элементовposition: stickyна базовой странице.