Предотвратить прокрутку тела при открытии модального - PullRequest
310 голосов
/ 02 марта 2012

Я хочу, чтобы мое тело перестало прокручиваться при использовании колесика мыши, пока модальное (с http://twitter.github.com/bootstrap) на моем сайте открыто.

Я пытался вызвать фрагмент JavaScript ниже, когда модал открыт, но безуспешно

$(window).scroll(function() { return false; });

AND

$(window).live('scroll', function() { return false; });

Обратите внимание, что на нашем сайте прекращена поддержка IE6, хотя IE7 + должен быть совместимым.

Ответы [ 41 ]

6 голосов
/ 28 августа 2016

Добавление класса 'is-modal-open' или изменение стиля тега body с помощью javascript - это нормально, и оно будет работать так, как должно. Но проблема, с которой мы столкнемся, заключается в том, что тело становится переполненным: скрытое, оно прыгнет наверх (scrollTop станет 0) Это станет проблемой юзабилити позже.

В качестве решения этой проблемы вместо изменения переполнения тега body: скрытый, измените его на html tag

$('#myModal').on('shown.bs.modal', function () {
  $('html').css('overflow','hidden');
}).on('hidden.bs.modal', function() {
  $('html').css('overflow','auto');
});
5 голосов
/ 22 сентября 2016

Для Bootstrap , вы можете попробовать это (работает на Firefox, Chrome и Microsoft Edge):

body.modal-open {
    overflow: hidden;
    position:fixed;
    width: 100%;
}

Надеюсь, это поможет...

3 голосов
/ 03 марта 2012

Вы можете использовать следующую логику, я протестировал ее, и она работает (даже в IE)

   <html>

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script>
<script type="text/javascript">

var currentScroll=0;
function lockscroll(){
    $(window).scrollTop(currentScroll);
}


$(function(){

        $('#locker').click(function(){
            currentScroll=$(window).scrollTop();
            $(window).bind('scroll',lockscroll);

        })  


        $('#unlocker').click(function(){
            currentScroll=$(window).scrollTop();
            $(window).unbind('scroll');

        })
})

</script>

<div>

<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<button id="locker">lock</button>
<button id="unlocker">unlock</button>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
<br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>

</div>
3 голосов
/ 29 августа 2013

Лучшее решение - это решение css-only body{overflow:hidden}, используемое в большинстве этих ответов. Некоторые ответы содержат исправление, которое также предотвращает «скачок», вызванный исчезающей полосой прокрутки; однако, ни один не был слишком изящен. Итак, я написал эти две функции, и они, кажется, работают довольно хорошо.

var $body = $(window.document.body);

function bodyFreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('overflow', 'hidden');
    $body.css('marginRight', ($body.css('marginRight') ? '+=' : '') + ($body.innerWidth() - bodyWidth))
}

function bodyUnfreezeScroll() {
    var bodyWidth = $body.innerWidth();
    $body.css('marginRight', '-=' + (bodyWidth - $body.innerWidth()))
    $body.css('overflow', 'auto');
}

Проверьте этот jsFiddle , чтобы увидеть его в использовании.

2 голосов
/ 01 марта 2016

На основе этой скрипки: http://jsfiddle.net/dh834zgw/1/

следующий фрагмент (с использованием jquery) отключит прокрутку окна:

 var curScrollTop = $(window).scrollTop();
 $('html').toggleClass('noscroll').css('top', '-' + curScrollTop + 'px');

А в вашем css:

html.noscroll{
    position: fixed;
    width: 100%;
    top:0;
    left: 0;
    height: 100%;
    overflow-y: scroll !important;
    z-index: 10;
 }

Теперь, когда вы удаляете модал, не забудьте удалить класс noscroll в теге html:

$('html').toggleClass('noscroll');
2 голосов
/ 21 декабря 2016

У меня была боковая панель, сгенерированная хаком флажка.Но основная идея заключается в том, чтобы сохранить документ scrollTop и не изменять его при прокрутке окна.

Мне просто не понравилось, что страница прыгает, когда тело становится «переполнением: скрыто».

window.addEventListener('load', function() {
    let prevScrollTop = 0;
    let isSidebarVisible = false;

    document.getElementById('f-overlay-chkbx').addEventListener('change', (event) => {
        
        prevScrollTop = window.pageYOffset || document.documentElement.scrollTop;
        isSidebarVisible = event.target.checked;

        window.addEventListener('scroll', (event) => {
            if (isSidebarVisible) {
                window.scrollTo(0, prevScrollTop);
            }
        });
    })

});
2 голосов
/ 18 апреля 2017

К сожалению, ни один из приведенных выше ответов не устранил мои проблемы.

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

Затем я пытался добавить .modal-open{overflow:auto;} (что рекомендовано большинством людей).Это действительно исправило проблемы: полоса прокрутки появляется после того, как я открываю модальное окно.Тем не менее, появляется еще один побочный эффект, который заключается в том, что «фон под заголовком немного сместится влево вместе с другим длинным баром позади модального» * ​​1006 *

Long bar behind modal

К счастью, после добавления {padding-right: 0 !important;} все исправлено идеально.И заголовок, и фон тела не двигались, и модал все еще держит полосу прокрутки.

Fixed image

Надеюсь, что это может помочь тем, кто все еще застрял с этимвопрос.Удачи!

2 голосов
/ 18 сентября 2017

Многие предлагают "переполнение: скрыто" на теле, которое не будет работать (по крайней мере, в моем случае), так как это заставит сайт прокручиваться вверх.

Это решение, которое работает для меня (как на мобильных телефонах, так и на компьютерах), используя jQuery:

    $('.yourModalDiv').bind('mouseenter touchstart', function(e) {
        var current = $(window).scrollTop();
        $(window).scroll(function(event) {
            $(window).scrollTop(current);
        });
    });
    $('.yourModalDiv').bind('mouseleave touchend', function(e) {
        $(window).off('scroll');
    });

Это заставит работать модальную прокрутку и предотвратит одновременную прокрутку сайта.

2 голосов
/ 03 апреля 2018

По состоянию на ноябрь 2017 года в Chrome введено новое свойство css

overscroll-behavior: contain;

, которое решает эту проблему, хотя на момент написания статьи ограничено кросс-браузерной поддержкой.

см. Нижессылки для полной информации и поддержки браузера

1 голос
/ 22 апреля 2015

Я просто сделал это так ...

$('body').css('overflow', 'hidden');

Но когда скроллер исчез, он переместил все правильно на 20 пикселей, поэтому я добавил

$('body').css('margin-right', '20px');

сразу после него.

У меня работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...