Отмена прокрутки страницы при открытом модльном окне (pop-up)

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

Это потому, что модальные окна являются элементами на странице, как и любые другие. Они могут оставаться на месте (при условии, что это то, что он должен делать), но остальная часть страницы может продолжать вести себя как обычно.

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.

Иногда это не проблема, например, экраны с точной высотой области просмотра. Но в других случаях, это может быть проблемой. Но есть хорошая новость. Она заключается в том, что мы можем предотвратить это с помощью CSS и JavaScript.

Давайте начнем с чего-то простого

Мы можем установить высоту body на полную высоту области просмотра и скрыв вертикальное переполнение, когда модальное окно открыто:

Это хорошо, но если мы прокрутили элемент <body> перед тем, как открыть модальное окно, то получим небольшое горизонтальное перекомпонование. Ширина области просмотра увеличивается примерно на 15 пикселей, что в точности соответствует ширине полосы прокрутки.

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.

Давайте немного откорректируем правый отступ body, чтобы избежать этого.

Обратите внимание, что модальное окно должно быть меньше, чем высота области просмотра, иначе полоса прокрутки на body будет необходима.

Отлично, теперь как насчет мобильного?

Это решение прекрасно работает как ПК, так и на Android . Тем не менее, Safari нужно немного больше любви, потому что body все еще прокручивается, когда модальное окно открыто и при касании перемещается по экрану.

Мы можем установить для body position: fixed:

Теперь будет работать. body не будет реагировать при прикосновении к экрану. Тем не менее, здесь все еще есть «маленькая» проблема. Допустим, модальный триггер находится внизу страницы, и мы нажимаем, чтобы открыть его. Отлично! Но теперь мы автоматически прокручиваем обратно до верхней части экрана, что столь же дезориентирует, как прокручиваемое поведение, которое мы пытаемся решить.

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.

Вот почему мы должны обратиться к JavaScript

Мы все знаем, что должен быть фоновый слой, когда открыто модальное окно. К сожалению, stopPropagation, немного не удобно работает с touch IOS. А вот preventDefault работает прекрасно. Это означает, что мы должны добавлять eventListenner в каждый узел DOM, содержащийся в модальном окне, а не только на фоне или на уровне модального блока. Хорошей новостью является то, что многие библиотеки JavaScript могут сделать это, в том числе хороший старый jQuery.

Да, и еще одна вещь: что если нам понадобится прокрутка внутри модального окна? Нам по-прежнему нужно инициировать ответ на прикосновение, но при достижении вершины или низа модального окна, нам все равно нужно предотвращать «пузырение». Сейчас рассмотри по подробнее…

Давайте улучшим подход с фиксированным body

Вот с чем мы работаем:

Если мы знаем верхнюю часть местоположения прокрутки и добавляем ее в наш CSS, то тело не будет прокручиваться обратно к верхней части экрана, поэтому проблема решена. Мы можем использовать JavaScript для этого, вычислив верхнюю часть прокрутки и добавив это значение к стилям тела:

Это работает, но все еще есть небольшая проблемка, после того, как закрываем моадльное окно. В частности, кажется, что страница уже теряет свою позицию прокрутки, когда модальное окно открыто и тело установлено фиксированным. Таким образом, мы должны восстановить местоположение. Давайте изменим наш JavaScript, чтобы учесть это.

Готово! body больше не прокручивается, когда модальное окно открыто, и положение прокрутки сохраняется как при открытом модале, так и при его закрытии. Ура!

See the Pen
Avoid body scrollable in safari when modal dialog shown
by Geoff Graham (@geoffgraham)
on CodePen.


Перевод статьи Brad Wu

Если у вас есть вопросы, или интересные темы для статьи, оставляйте свои комментарии 🙂

Так же подписывайтесь на наш телеграм-канал, чтобы всегда быть вкурсе новых статей 🙂

Оставьте ответ

comment-avatar

*