Як програмно відключити прокрутку сторінки за допомогою jQuery


163

Використовуючи jQuery, я хотів би відключити прокрутку тіла:

Моя ідея:

  1. Встановити body{ overflow: hidden;}
  2. Захоплення струмом scrollTop();/scrollLeft()
  3. Прив’яжіть до події прокрутки тіла, встановіть scrollTop / scrollLeft на захоплене значення.

Чи є кращий спосіб?


Оновлення:

Будь ласка, ознайомтесь із моїм прикладом та причиною, чому на http://jsbin.com/ikuma4/2/edit

Я усвідомлюю, що хтось подумає "чому він не просто використовує position: fixed на панелі?".

Будь ласка, не пропонуйте цього, оскільки у мене є інші причини.


7
"Чи є кращий спосіб?" - крім того, щоб браузер не поводився нормально?
Фентон

22
"мелодраматично"?
Майк Веллер

6
Можливо, мається на увазі програмно? Оскільки це пропозиція щодо виправлення орфографії для виправлення правопису для "програмно"
Майкл Шіммінс,

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 скидає положення прокрутки назад, куди вам потрібно.
tfe

1
Крім того, якби тіло мало переповнення чогось іншого, окрім цього auto, воно буде перезаписане. Мені потрібно було зберегти існуючий параметр, щоб це також додало деякі накладні витрати.
tfe

Хтось знає, чому просто стайлінг htmlта bodyз overflow: hiddenнедостатньою? Ми все ще потребуємо обробника подій.
kpozin

4
Це фантастична відповідь. А щоб він працював на сенсорних пристроях, ознайомтеся з цією відповіддю.
Патрік

235

Це повністю відключить прокрутку:

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

Відновити:

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

Тестували його на Firefox та Chrome.


18
працює як очікувалося. Дякую! Це повинна була бути прийнята відповідь!
Дейв Чен

6
Ще прокручується із середньою кнопкою миші на хромі.
Лотар

16
При цьому втрачається поточне положення прокрутки. OP чітко згадував про захоплення позиції прокрутки, тому я припускаю, що він цього вимагав. У будь-якому випадку, я вимагаю цього, тому це для мене обмежене використання
zerm

7
PS Опускання height: 100%ефективно блокує прокрутку в поточному положенні без стрибків - принаймні на останньому Chrome.
zerm

2
Це НЕ правильна відповідь. Позиція прокрутки не захоплюється
taylorcressy

43

спробуйте це

$('#element').on('scroll touchmove mousewheel', function(e){
  e.preventDefault();
  e.stopPropagation();
  return false;
})

просто те, що я шукав ... майже. У будь-якому разі відключити його під час клавіш зі стрілками?
Коді

2
@Cody - поєднайте це з переповненням css: приховано
Darius.V

2
@cubbiu як його змінити?
Meer

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});
Йохансрк

Власне, просто користуйся marginRightі marginLeft:)
Martijn

25

Ви можете використовувати цей код:

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

8
Ще можна використовувати середню кнопку миші для прокрутки.
Роджер Фар

2
Ні, це нормально, і з цим не прокручуйте!
mr.soroush

Якщо ви використовуєте додатковий css, який МОЖЕТЕ повністю відключити прокрутку, див. Мою відповідь для отримання більш детальної інформації.
gitaarik

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 (), щоб тимчасово відключити прокрутку, почувши подію рухомого колеса / прокрутки, але це не працює. Якийсь шанс ви знаєте спосіб досягти цього ефекту?
жовто-святий

@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/


1
Це правильна відповідь. Не знаєте, чому його не встановили як він
Гільгерме Феррейра

Це працює. Просто потрібен код скидання, розміщений на відповідь Патріка
Hastig Zusammenstellen

4

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

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

редагувати : У жодному разі немає необхідності в jQuery, нижче такого ж, як у ванільній JS (це означає, що немає фреймів, просто JavaScript):

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

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

this.body.scrollTop - сумісність IE




3

Хтось опублікував цей код, у якого проблема не зберегти положення прокрутки при відновленні. Причина полягає в тому, що люди, як правило, застосовують його до html та body або просто тіло, але його слід застосовувати лише до html. Таким чином, при відновленні положення прокрутки буде збережено:

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

Відновити:

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

не 'overflow': 'auto',користуватися'overflow': 'initial',
evtuhovdo

2

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

  • Завантажте демонстраційний поштовий індекс: 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.

Якщо ви хочете отримати додаткову допомогу, опублікуйте, де ви встанете!

Сподіваюся, що це допомогло.



1

Якщо ви просто хочете відключити прокрутку за допомогою навігації на клавіатурі, ви можете змінити подію клавіші.

$(document).on('keydown', function(e){
    e.preventDefault();
    e.stopPropagation();
});

1

Спробуйте цей код:

    $(function() { 
        // ...

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

        // ...
    });

0

Ви можете прикрити вікно прокручуваним ділом, щоб запобігти прокрученню вмісту на сторінці. І, сховавши та показавши, ви можете заблокувати / розблокувати свій сувій.

Зробіть щось подібне:

#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();
}

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


Редагувати: зауважте, що я не маю поняття, як погано це може бути (читай: підірвати) на сенсорному пристрої.


0

Ви також можете використовувати DOM для цього. Скажіть, у вас є така функція, яку ви викликаєте так:

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

І це все є! Сподіваюся, це допомагає на додаток до всіх інших відповідей!


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, але, без сумніву, його можна застосувати до будь-якого елемента, що викликає подію прокрутки.

Просто встановіть та вимкніть прокруткуLock як потрібно.

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

Сподіваюся, що цей комусь допомагає.


Цей працює як слід, за одним винятком. Коли сувій заблокований, а я прокручую, він трохи
посмикується

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)
})

Цей слухач подій повинен заблокувати прокручування. Просто видаліть їх, щоб повторно включити прокрутку

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.