Как программно отключить прокрутку страницы с помощью jQuery

163

Используя jQuery, я бы хотел отключить прокрутку тела:

Моя идея состоит в том, чтобы:

  1. Устанавливать body{ overflow: hidden;}
  2. Захватить текущий scrollTop();/scrollLeft()
  3. Привязать к событию прокрутки тела, установите scrollTop / scrollLeft в захваченное значение.

Есть ли способ лучше?


Обновить:

Пожалуйста, посмотрите мой пример и причину, по которой, на http://jsbin.com/ikuma4/2/edit

Я знаю, что кто-то подумает: «Почему он не просто использует position: fixedпанель?».

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

Hailwood
источник
7
"Есть ли способ лучше?" - кроме как позволить браузеру вести себя нормально?
Фентон
22
«театрально»?
Майк Веллер
6
Возможно, подразумевается программно? Так как это предложение Firefox по исправлению орфографии для «программно»
Майкл Шимминс
4
Эта тема собирается \ b \
Cipi
3
@ Sohnee отключить прокрутку! == плохо
Mansiemans

Ответы:

136

Единственный способ сделать это похож на то, что вы описали:

  1. Возьмите текущую позицию прокрутки (не забудьте горизонтальную ось!).
  2. Установите переполнение скрытым (вероятно, хотите сохранить предыдущее значение переполнения).
  3. Прокрутите документ до сохраненной позиции прокрутки с помощью scrollTo ().

Затем, когда вы будете готовы снова разрешить прокрутку, отмените все это.

Изменить: нет причин, я не могу дать вам код, так как я попытался выкопать его ...

// lock scroll position, but retain settings for later
var scrollPosition = [
  self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
  self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var html = jQuery('html'); // it would make more sense to apply this to body, but IE7 won't have that
html.data('scroll-position', scrollPosition);
html.data('previous-overflow', html.css('overflow'));
html.css('overflow', 'hidden');
window.scrollTo(scrollPosition[0], scrollPosition[1]);


// un-lock scroll position
var html = jQuery('html');
var scrollPosition = html.data('scroll-position');
html.css('overflow', html.data('previous-overflow'));
window.scrollTo(scrollPosition[0], scrollPosition[1])
т.у.т.
источник
2
пожалуйста, посмотрите jsbin.com/ikuma4/2/edit и объясните мне причину, что ваша лучше? я что-то упускаю (я спрашиваю, потому что не вижу причин для длины вашего ответа по сравнению с моим примером)
Hailwood
3
Ваш подход не работает в IE7. Я тоже сначала попробовал. Проблема в том, что он не реагирует на событие прокрутки достаточно быстро. Он позволяет документу прокручиваться, а затем привязывает его обратно, когда ваш JS сбрасывает позицию прокрутки туда, куда вы хотите.
т.у.т.
1
Кроме того, если тело имеет переполнение чего-либо другого auto, оно будет перезаписано. Мне нужно было сохранить существующую настройку, так что это добавляет некоторые накладные расходы.
т.у.т.
Кто-нибудь знает, почему просто стиль htmlи bodyс overflow: hiddenнедостаточно? Нам все еще нужен обработчик событий.
кпозин
4
Это фантастический ответ. И чтобы заставить его работать на сенсорных устройствах, проверьте этот ответ.
Патрик
235

Это полностью отключит прокрутку:

$('html, body').css({
    overflow: 'hidden',
    height: '100%'
});

Восстановить:

$('html, body').css({
    overflow: 'auto',
    height: 'auto'
});

Протестировал его на Firefox и Chrome.

gitaarik
источник
18
работает как положено. Спасибо! Это должен был быть принятый ответ!
Дэйв Чен
6
Все еще прокручивает с помощью средней кнопки мыши на хром.
Лотар
16
Это теряет текущую позицию прокрутки. OP явно упомянул о захвате позиции прокрутки, так что я предполагаю, что он требовал этого. В любом случае, я нуждаюсь в этом, так что это ограниченное использование для меня
zerm
7
PS Опускание height: 100%эффективно блокирует прокрутку в текущей позиции без прыжков - по крайней мере, на последнем Chrome.
Зер
2
Это НЕ правильный ответ. Положение свитка не захвачено
taylorcressy
43

попробуй это

$('#element').on('scroll touchmove mousewheel', function(e){
  e.preventDefault();
  e.stopPropagation();
  return false;
})
cubbiu
источник
только то, что я искал ... почти. Во всяком случае, чтобы отключить его во время клавиш со стрелками?
Коди
2
@Cody - объедините это с переполнением CSS: скрыто
Darius.V
2
@ Куббиу, как повернуть его вспять?
Меер
3
Вы можете использовать$('#element').off('scroll touchmove mousewheel');
arnuschky
1
Отличное решение. Хотя как бы вы отключили только bodyпрокрутку, но разрешить прокрутку внутри других дочерних элементов overflow: scroll?
Fizzix
27

Я просто привожу небольшую настройку решения от tfe . В частности, я добавил некоторые дополнительные элементы управления, чтобы гарантировать отсутствие смещения содержимого страницы (или сдвига страницы ), когда полоса прокрутки установлена ​​в hidden.

Две функции Javascript lockScroll()и unlockScroll()могут быть определены, соответственно, для блокировки и разблокировки прокрутки страницы.

function lockScroll(){
    $html = $('html'); 
    $body = $('body'); 
    var initWidth = $body.outerWidth();
    var initHeight = $body.outerHeight();

    var scrollPosition = [
        self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
        self.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
    ];
    $html.data('scroll-position', scrollPosition);
    $html.data('previous-overflow', $html.css('overflow'));
    $html.css('overflow', 'hidden');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);   

    var marginR = $body.outerWidth()-initWidth;
    var marginB = $body.outerHeight()-initHeight; 
    $body.css({'margin-right': marginR,'margin-bottom': marginB});
} 

function unlockScroll(){
    $html = $('html');
    $body = $('body');
    $html.css('overflow', $html.data('previous-overflow'));
    var scrollPosition = $html.data('scroll-position');
    window.scrollTo(scrollPosition[0], scrollPosition[1]);    

    $body.css({'margin-right': 0, 'margin-bottom': 0});
}

где я предположил, что <body>не имеет начальной маржи.

Обратите внимание, что, хотя вышеупомянутое решение работает в большинстве практических случаев, оно не является окончательным, поскольку оно требует некоторой дополнительной настройки для страниц, которые включают, например, заголовок с position:fixed. Давайте перейдем к этому частному случаю с примером. Предположим, чтобы иметь

<body>
<div id="header">My fixedheader</div>
<!--- OTHER CONTENT -->
</body>

с участием

#header{position:fixed; padding:0; margin:0; width:100%}

Затем следует добавить следующее в функции lockScroll()и unlockScroll():

function lockScroll(){
    //Omissis   


    $('#header').css('margin-right', marginR);
} 

function unlockScroll(){
    //Omissis   

    $('#header').css('margin-right', 0);
}

Наконец, позаботьтесь о возможном начальном значении полей или отступов.

Жан Вальжан
источник
4
У вас есть ошибка в вашем javascript $ body.css ({'margin-right': 0, 'margin-bottom', 0}); должно быть $ body.css ({'margin-right': 0, 'margin-bottom': 0});
Johansrk
На самом деле, просто используйте marginRightи marginLeft:)
Martijn
25

Вы можете использовать этот код:

$("body").css("overflow", "hidden");
mr.soroush
источник
8
Вы все еще можете использовать среднюю кнопку мыши для прокрутки.
Роджер Фар
2
Нет, это нормально, и без этого свитка!
mr.soroush
Если вы используете некоторые дополнительные CSS, вы можете полностью отключить прокрутку, см. Мой ответ для более подробной информации.
Гитаарик
21

Чтобы отключить прокрутку, попробуйте это:

var current = $(window).scrollTop();
$(window).scroll(function() {
    $(window).scrollTop(current);
});

сбросить:

$(window).off('scroll');
Патрик ДаВейдер
источник
Это было фантастическое решение для того, что мне было нужно.
Терри Картер
@EveryScreamer нет, экран трясется как сумасшедший. Пытаюсь найти обходной путь.
Телариан
5

Я написал плагин jQuery для обработки этого: $ .disablescroll .

Он предотвращает прокрутку от событий колесика мыши, касания и нажатия клавиш, например Page Down.

Здесь есть демо .

Использование:

$(window).disablescroll();

// To re-enable scrolling:
$(window).disablescroll("undo");
Джош Харрисон
источник
Я пытался использовать ваш плагин disablescroll (), чтобы временно отключить прокрутку при прослушивании события mouswheel / scroll, но он не работает. Есть ли шанс, что вы знаете способ достижения этого эффекта?
желто-святого
@JB Я, вероятно, могу помочь, но комментарии не лучшее место. Присоединяйтесь ко мне в этом чате с переполнением стека, и я посмотрю, что я могу сделать: chat.stackoverflow.com/rooms/55043/disablescroll-usage
Джош Харрисон
Извините, но этот плагин даже не работает в вашем jsfiddle.
markj
Вы можете помочь мне проверить это, сообщив мне, в каком браузере / платформе он не работает, пожалуйста?
Джош Харрисон
5

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

var $window = $(window);

$window.on("mousewheel DOMMouseScroll", onMouseWheel);

function onMouseWheel(e) {
    e.preventDefault();
}

https://jsfiddle.net/22cLw9em/

dzimi
источник
1
Это правильный ответ. Не знаю, почему это не установлено, как это
Гильерме Феррейра
Оно работает. Просто нужен код сброса, опубликованный для соответствия ответу Патрика
Хастиг Зусамменстеллен
4

Один вкладыш для отключения прокрутки, включая среднюю кнопку мыши.

$(document).scroll(function () { $(document).scrollTop(0); });

edit : в любом случае нет необходимости в jQuery, ниже, как и в vanilla JS (это означает, что нет фреймворков, только JavaScript):

document.addEventListener('scroll', function () { this.documentElement.scrollTop = 0; this.body.scrollTop = 0; })

this.documentElement.scrollTop - стандартный

this.body.scrollTop - IE совместимость

Pawel
источник
4
  • Чтобы скрыть свиток: $("body").css("overflow", "hidden");
  • Чтобы восстановить прокрутку: $("body").css("overflow", "initial");
Джоан Альберто Агилар Пенья
источник
3

Разве вы не можете просто установить рост на 100% и скрыть переполнение? Смотрите http://jsbin.com/ikuma4/13/edit

Адриан Шмидт
источник
$ ("html"). css ({высота: '100%', переполнение: 'скрыто'}); Это просто работает, спасибо Адриан
Алексей
3

Кто-то опубликовал этот код, у которого есть проблема не сохранения позиции прокрутки при восстановлении. Причина в том, что люди склонны применять его к html и body или просто к телу, но его следует применять только к html. Таким образом, при восстановлении положение прокрутки будет сохранено:

$('html').css({
    'overflow': 'hidden',
    'height': '100%'
});

Восстановить:

$('html').css({
    'overflow': 'auto',
    'height': 'auto'
});
Mescalina
источник
не 'overflow': 'auto',использовать'overflow': 'initial',
evtuhovdo
2

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

  • Загрузите демоверсию zip: http://github.com/vitch/jScrollPane/archives/master
  • Откройте демо "События" (events.html)
  • Отредактируйте его, чтобы использовать не минимизированный источник скрипта: <script type="text/javascript" src="script/jquery.jscrollpane.js"></script>
  • В jquery.jscrollpane.js вставьте «return;» в строке 666 (благоприятный номер строки! но если ваша версия немного отличается, это первая строка positionDragY(destY, animate)функции

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

Таким способом вы можете управлять полосами прокрутки всего браузера (см. Fullpage_scroll.html).

Итак, предположительно, следующим шагом является добавление вызова к какой-либо другой функции, которая отключается и выполняет магию привязки, а затем решает, продолжать ли прокрутку или нет. У вас также есть вызовы API для установки scrollTop и scrollLeft.

Если вам нужна дополнительная помощь, напишите, где вы находитесь до!

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

Джереми Варн
источник
2

Я поставил ответ, который может помочь здесь: jQuery simplemodal отключить прокрутку

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

mhenry1384
источник
1

Если вы просто хотите отключить прокрутку с помощью навигации по клавиатуре, вы можете отменить событие нажатия клавиши.

$(document).on('keydown', function(e){
    e.preventDefault();
    e.stopPropagation();
});
Sean
источник
1

Попробуйте этот код:

    $(function() { 
        // ...

        var $body = $(document);
        $body.bind('scroll', function() {
            if ($body.scrollLeft() !== 0) {
                $body.scrollLeft(0);
            }
        });

        // ...
    });
Jopie
источник
0

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

Сделайте что-то вроде этого:

#scrollLock {
    width: 100%;
    height: 100%;
    position: fixed;
    overflow: scroll;
    opacity: 0;
    display:none
}

#scrollLock > div {
    height: 99999px;
}

function scrollLock(){
    $('#scrollLock').scrollTop('10000').show();
}

function scrollUnlock(){
    $('#scrollLock').hide();
}
Appex
источник
7
Пожалуйста, не используйте сокращения, такие как "u" и "smth". Потратьте время, чтобы написать правильно, для удобства чтения.
Жестянщик
0

Для людей, которые имеют центрированные макеты (через margin:0 auto;), здесь приведен список position:fixedрешений вместе с предлагаемым решением @tfe .

Используйте это решение, если вы испытываете щелчок страницы (из-за показа / скрытия полосы прокрутки).

// lock scroll position, but retain settings for later
var scrollPosition = [
    window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
    window.pageYOffset || document.documentElement.scrollTop  || document.body.scrollTop
];
var $html = $('html'); // bow to the demon known as MSIE(v7)
$html.addClass('modal-noscroll');
$html.data('scroll-position', scrollPosition);
$html.data('margin-top', $html.css('margin-top'));
$html.css('margin-top', -1 * scrollPosition[1]);

…в сочетании с…

// un-lock scroll position
var $html = $('html').removeClass('modal-noscroll');
var scrollPosition = $html.data('scroll-position');
var marginTop = $html.data('margin-top');
$html.css('margin-top', marginTop);
window.scrollTo(scrollPosition[0], scrollPosition[1])

... и, наконец, CSS для .modal-noscroll...

.modal-noscroll
{
    position: fixed;
    overflow-y: scroll;
    width: 100%;
}

Я бы рискнул сказать , что это более полное решение , чем любой из других решений там, но я не проверял , что полностью еще ...: P


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

Matthemattics
источник
0

Вы также можете использовать DOM для этого. Скажем, у вас есть функция, которую вы вызываете так:

function disable_scroll() {
document.body.style.overflow="hidden";
}

И это все, что нужно сделать! Надеюсь, что это помогает в дополнение ко всем другим ответам!

Brendan
источник
0

Это то, что я в итоге сделал:

CoffeeScript:

    $("input").focus ->
        $("html, body").css "overflow-y","hidden"
        $(document).on "scroll.stopped touchmove.stopped mousewheel.stopped", (event) ->
            event.preventDefault()

    $("input").blur ->
        $("html, body").css "overflow-y","auto"
        $(document).off "scroll.stopped touchmove.stopped mousewheel.stopped"

Javascript:

$("input").focus(function() {
 $("html, body").css("overflow-y", "hidden");
 $(document).on("scroll.stopped touchmove.stopped mousewheel.stopped", function(event) {
   return event.preventDefault();
 });
});

$("input").blur(function() {
 $("html, body").css("overflow-y", "auto");
 $(document).off("scroll.stopped touchmove.stopped mousewheel.stopped");
});
марза
источник
0

Не уверен, что кто-нибудь попробовал мое решение. Этот работает для всего тела / html, но, без сомнения, он может быть применен к любому элементу, который запускает событие прокрутки.

Просто установите и снимите scrollLock, как вам нужно.

var scrollLock = false;
var scrollMem = {left: 0, top: 0};

$(window).scroll(function(){
    if (scrollLock) {
        window.scrollTo(scrollMem.left, scrollMem.top);
    } else {
        scrollMem = {
            left: self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
            top: self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
        };
    }
});

Вот пример JSFiddle

Надеюсь, этот поможет кому-нибудь.

FossilMFC
источник
Этот работает как надо, за одним исключением. Когда свиток заблокирован, и я прокручиваю, он немного дергается, прежде чем фактически заблокировать свиток ...
Томас Тейлманн
0

Я думаю, что лучшее и чистое решение:

window.addEventListener('scroll',() => {
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y);
});

И с помощью jQuery:

$(window).on('scroll',() => {
    var x = window.scrollX;
    var y = window.scrollY;
    window.scrollTo(x,y)
})

Эти прослушиватели событий должны блокировать прокрутку. Просто удалите их, чтобы снова включить прокрутку

Tiziano
источник