如何暂时禁用滚动?

Oli*_*nde 412 javascript jquery scroll

我正在使用scrollTo jQuery插件,并想知道是否有可能通过Javascript临时禁用滚动窗口元素?我想要禁用滚动的原因是当你滚动时scrollTo是动画,它变得非常丑陋;)

当然,我可以做一个$("body").css("overflow", "hidden");然后在动画停止时将其恢复为自动,但如果滚动条仍然可见但不活动会更好.

gbl*_*zex 697

scroll活动无法取消.但是你可以通过取消这些交互事件来实现:
鼠标 触摸滚动以及与滚动相关的按钮.

[ 工作演示 ]

// left: 37, up: 38, right: 39, down: 40,
// spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
var keys = {37: 1, 38: 1, 39: 1, 40: 1};

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault)
      e.preventDefault();
  e.returnValue = false;  
}

function preventDefaultForScrollKeys(e) {
    if (keys[e.keyCode]) {
        preventDefault(e);
        return false;
    }
}

function disableScroll() {
  if (window.addEventListener) // older FF
      window.addEventListener('DOMMouseScroll', preventDefault, false);
  document.addEventListener('wheel', preventDefault, {passive: false}); // Disable scrolling in Chrome
  window.onwheel = preventDefault; // modern standard
  window.onmousewheel = document.onmousewheel = preventDefault; // older browsers, IE
  window.ontouchmove  = preventDefault; // mobile
  document.onkeydown  = preventDefaultForScrollKeys;
}

function enableScroll() {
    if (window.removeEventListener)
        window.removeEventListener('DOMMouseScroll', preventDefault, false);
    document.removeEventListener('wheel', preventDefault, {passive: false}); // Enable scrolling in Chrome
    window.onmousewheel = document.onmousewheel = null; 
    window.onwheel = null; 
    window.ontouchmove = null;  
    document.onkeydown = null;  
}
Run Code Online (Sandbox Code Playgroud)

  • 其他开发人员在此陷阱中的提示:请确保从其他jQuery尝试中删除任何和所有'e.stopPropagation()'调用以停止滚动,因为它不仅无效,还会阻止事件冒泡到此代码这工作.希望我浪费30分钟将有助于节省别人的时间:) (109认同)
  • 我可以像往常一样滚动它:使用中键按下并移动鼠标...因此这个技巧不会影响像我这样的用户;) (11认同)
  • 滚动条未禁用. (9认同)
  • 您可以向禁用的键数组添加32(空格)(显示在代码注释中). (4认同)
  • 我仍然可以通过在页面的顶部/底部拖动文件来使其滚动。这也可以通过选择页面上的文本并在顶部/底部进行相同的拖动来实现。 (3认同)
  • 鼠标中键和选择文本均会导致滚动...您可以禁用选择,但这是不良的ui实践 (2认同)
  • 当心!!此方法可能不适合您在模态内滚动的情况! (2认同)
  • 这在Chrome上不再起作用 (2认同)

hal*_*dom 415

只需在主体中添加一个类即可:

.stop-scrolling {
  height: 100%;
  overflow: hidden;
}
Run Code Online (Sandbox Code Playgroud)

添加该类,然后在要重新启用滚动时删除,在IE,FF,Safari和Chrome中进行测试.

$('body').addClass('stop-scrolling')
Run Code Online (Sandbox Code Playgroud)

对于移动设备,您需要处理该touchmove事件:

$('body').bind('touchmove', function(e){e.preventDefault()})
Run Code Online (Sandbox Code Playgroud)

并解除绑定以重新启用滚动.在iOS6和Android 2.3.3中测试过

$('body').unbind('touchmove')
Run Code Online (Sandbox Code Playgroud)

  • 虽然此解决方案确实有效,但它具有滚动回页面顶部的(可能)不良影响. (59认同)
  • 此解决方案有效但滚动条消失并在将此类应用于正文时创建"凹凸"效果(在窗口os下)(例如) (20认同)
  • 得到它了!你必须处理`touchmove`事件,就像`$('body').bind('touchmove',function(e){e.preventDefault()})`.编辑此答案以包含此移动解决方案. (4认同)
  • 很酷,只需要确保任何内部滚动可以在触摸设备的模态中工作.可以在模态下方进行叠加,并防止覆盖层上的默认触摸移动而不是主体. (3认同)
  • 除非我的选择器是`$('body,html')`,否则这对我不起作用 (3认同)
  • 这也会阻止滚动事件触发.只是在说' (3认同)
  • 使用@MusikAnimal解决方案禁用移动视口滚动,同时使用`overflow:scroll`在子元素上启用它.你可以用`$('.child').bind("touchmove",function(e){e.stopPropagation()})来做到这一点. (2认同)
  • 这很棒.我喜欢它多么聪明和简单.让我超越人们所遇到的其他问题的原因是让`html`最初设置为`position:absolute; 宽度:100%; 身高:100%; overflow-y:scroll`.(我总是添加`overflow-y:scroll`到`html`,不能推荐它).然后在`.stop-scrolling`中,只在`html`上切换,你需要的只是`overflow-y:hidden`.瞧,没有更多的内容跳来跳去.(适用于Chrome 43.0.2357.132(64位)OS X Yosemite) (2认同)
  • @matt跳转到顶部问题的任何变通方法?一直在努力:http://doubledutch.me/product/spring-release-2016/ (2认同)
  • 在最重要的问题上,我只有在将.position-fixed属性添加到.stop-scrolling类中时才遇到它。否则,我也不会遇到这个问题。 (2认同)

sdl*_*rhc 55

这是一个非常基本的方法:

window.onscroll = function () { window.scrollTo(0, 0); };
Run Code Online (Sandbox Code Playgroud)

这在IE6中是一种跳跃式的.

  • 实际上并不是禁用,更像是在尝试滚动时捕捉到默认值. (14认同)
  • 恕我直言 - 这里最好的答案.另外,您不必将其锁定为`(0,0)`,只需使用当前滚动位置即可. (11认同)
  • @Marcus尽管它可以获得一个不可取消的事件. (10认同)
  • 但是我们如何重新启用它? (3认同)
  • 即使它没有真正禁用它,它模拟它,这对我来说已经足够了. (2认同)

Moh*_*ini 36

以下解决方案是基本但纯JavaScript(没有jQuery):

function disableScrolling(){
    var x=window.scrollX;
    var y=window.scrollY;
    window.onscroll=function(){window.scrollTo(x, y);};
}

function enableScrolling(){
    window.onscroll=function(){};
}
Run Code Online (Sandbox Code Playgroud)

  • 在Safari 7.1和IE 11中跳跃.最新的Chrome,Firefox,Opera ok. (3认同)
  • 你可以设置`window.onscroll=null`而不是添加一个空的匿名函数,`null`是`window.onload`的初始值 (3认同)
  • 在最新的 Chrome 上仍然有点紧张 (2认同)

Jos*_*son 25

此解决方案将保持当前滚动位置,同时禁用滚动,这与将用户跳回到顶部的一些不同.

它基于galambalazs的回答,但支持触摸设备,并使用jquery插件包装器重构为单个对象.

在这里演示.

在github这里.

/**
 * $.disablescroll
 * Author: Josh Harrison - aloof.co
 *
 * Disables scroll events from mousewheels, touchmoves and keypresses.
 * Use while jQuery is animating the scroll position for a guaranteed super-smooth ride!
 */

;(function($) {

    "use strict";

    var instance, proto;

    function UserScrollDisabler($container, options) {
        // spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36
        // left: 37, up: 38, right: 39, down: 40
        this.opts = $.extend({
            handleKeys : true,
            scrollEventKeys : [32, 33, 34, 35, 36, 37, 38, 39, 40]
        }, options);

        this.$container = $container;
        this.$document = $(document);
        this.lockToScrollPos = [0, 0];

        this.disable();
    }

    proto = UserScrollDisabler.prototype;

    proto.disable = function() {
        var t = this;

        t.lockToScrollPos = [
            t.$container.scrollLeft(),
            t.$container.scrollTop()
        ];

        t.$container.on(
            "mousewheel.disablescroll DOMMouseScroll.disablescroll touchmove.disablescroll",
            t._handleWheel
        );

        t.$container.on("scroll.disablescroll", function() {
            t._handleScrollbar.call(t);
        });

        if(t.opts.handleKeys) {
            t.$document.on("keydown.disablescroll", function(event) {
                t._handleKeydown.call(t, event);
            });
        }
    };

    proto.undo = function() {
        var t = this;
        t.$container.off(".disablescroll");
        if(t.opts.handleKeys) {
            t.$document.off(".disablescroll");
        }
    };

    proto._handleWheel = function(event) {
        event.preventDefault();
    };

    proto._handleScrollbar = function() {
        this.$container.scrollLeft(this.lockToScrollPos[0]);
        this.$container.scrollTop(this.lockToScrollPos[1]);
    };

    proto._handleKeydown = function(event) {
        for (var i = 0; i < this.opts.scrollEventKeys.length; i++) {
            if (event.keyCode === this.opts.scrollEventKeys[i]) {
                event.preventDefault();
                return;
            }
        }
    };


    // Plugin wrapper for object
    $.fn.disablescroll = function(method) {

        // If calling for the first time, instantiate the object and save
        // reference. The plugin can therefore only be instantiated once per
        // page. You can pass options object in through the method parameter.
        if( ! instance && (typeof method === "object" || ! method)) {
            instance = new UserScrollDisabler(this, method);
        }

        // Instance already created, and a method is being explicitly called,
        // e.g. .disablescroll('undo');
        else if(instance && instance[method]) {
            instance[method].call(instance);
        }

    };

    // Global access
    window.UserScrollDisabler = UserScrollDisabler;

})(jQuery);
Run Code Online (Sandbox Code Playgroud)


lis*_*aro 15

我很遗憾回答一篇旧帖子,但我正在寻找解决方案并遇到了这个问题.

此问题有许多解决方法仍然显示滚动条,例如为容器提供100%的高度和overflow-y: scroll样式.

在我的情况下,我刚刚创建了一个带有滚动条的div,我在添加overflow: hidden到正文时显示:

function disableScroll() {
    document.getElementById('scrollbar').style.display = 'block';
    document.body.style.overflow = 'hidden';
}
Run Code Online (Sandbox Code Playgroud)

元素滚动条必须具有以下样式:

overflow-y: scroll; top: 0; right: 0; display: none; height: 100%; position: fixed;
Run Code Online (Sandbox Code Playgroud)

这显示了一个灰色滚动条,希望它可以帮助未来的访问者.


Văn*_*yết 15

var winX = null;
var winY = null;

window.addEventListener('scroll', function () {
    if (winX !== null && winY !== null) {
        window.scrollTo(winX, winY);
    }
});

function disableWindowScroll() {
    winX = window.scrollX;
    winY = window.scrollY;
}

function enableWindowScroll() {
    winX = null;
    winY = null;
}
Run Code Online (Sandbox Code Playgroud)

  • 这是这里最好的解决方案。 (4认同)

Raj*_*pta 8

我一直在寻找这个问题的解决方案但是对上述任何一个解决方案都不满意(截至写这个答案),所以我提出了这个解决方案..

CSS

.scrollDisabled {   
    position: fixed;
    margin-top: 0;// override by JS to use acc to curr $(window).scrollTop()
    width: 100%;
}
Run Code Online (Sandbox Code Playgroud)

JS

var y_offsetWhenScrollDisabled=0;

function disableScrollOnBody(){
    y_offsetWhenScrollDisabled= $(window).scrollTop();
    $('body').addClass('scrollDisabled').css('margin-top', -y_offsetWhenScrollDisabled);
}
function enableScrollOnBody(){
    $('body').removeClass('scrollDisabled').css('margin-top', 0);
    $(window).scrollTop(y_offsetWhenScrollDisabled);
}
Run Code Online (Sandbox Code Playgroud)


小智 8

此答案提出了一种解决方案,用于消除应用此解决方案overflow: hidden中的建议时发生的“碰撞” 。由于编辑被拒绝,这里是:


要消除应用时发生的“凹凸”overflow: hidden,您可以计算滚动条的宽度并将其替换为边距。这是该元素的示例body

const bodyScrollControls = {
  scrollBarWidth: window.innerWidth - document.body.clientWidth,

  disable() {
    document.body.style.marginRight = `${this.scrollBarWidth}px`;
    document.body.style.overflowY = 'hidden';
  },
  enable() {
    document.body.style.marginRight = null;
    document.body.style.overflowY = null;
  },
};
Run Code Online (Sandbox Code Playgroud)

如果某个元素已经有margin-right,那么获取现有元素并向其添加滚动条宽度应该不是问题。


小智 7

根据galambalazs帖子,我会添加对触摸设备的支持,允许我们触摸但不向上或向下滚动:

function disable_scroll() {
   ...
   document.ontouchmove = function(e){ 
        e.preventDefault(); 
   }
}

function enable_scroll() {
   ...
   document.ontouchmove = function(e){ 
     return true; 
   }
}
Run Code Online (Sandbox Code Playgroud)

  • 你确定它的答案不仅仅是对其他答案的评论吗? (3认同)

小智 7

不,我不会使用事件处理,因为:

  • 并非所有事件都能保证到达身体,

  • 选择文本并向下移动实际上会滚动文档,

  • 如果在事件分离阶段出现问题,你注定要失败。

我通过使用隐藏的文本区域进行复制粘贴操作而被此咬住了,猜猜是什么,每当我进行复制时页面都会滚动,因为在内部我必须在调用之前选择文本区域 document.execCommand('copy').

无论如何,这就是我要走的路,请注意setTimeout()

document.body.setAttribute('style','overflow:hidden;');
// do your thing...
setTimeout(function(){document.body.setAttribute('style','overflow:visible;');}, 500);
Run Code Online (Sandbox Code Playgroud)

当滚动条暂时消失时,存在闪烁的动量,但这是可以接受的。


Hok*_*cha 6

从Chrome 56和其他现代浏览器开始,您必须添加passive:falseaddEventListener通话中才能preventDefault正常工作。所以我用它来停止在手机上滚动:

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

function disableScroll(){
    document.body.addEventListener('touchmove', preventDefault, { passive: false });
}
function enableScroll(){
    document.body.removeEventListener('touchmove', preventDefault, { passive: false });
}
Run Code Online (Sandbox Code Playgroud)


axe*_*a82 5

根据您想要通过删除的滚动实现的目标,您可以修复要从中删除滚动的元素(单击或您想要暂时停用滚动的任何其他触发器)

我正在寻找“临时无滚动”解决方案,并且根据我的需要,这解决了它

上课

.fixed{
    position: fixed;
}
Run Code Online (Sandbox Code Playgroud)

然后用Jquery

var someTrigger = $('#trigger'); //a trigger button
var contentContainer = $('#content'); //element I want to temporarily remove scroll from

contentContainer.addClass('notfixed'); //make sure that the element has the "notfixed" class

//Something to trigger the fixed positioning. In this case we chose a button.
someTrigger.on('click', function(){

    if(contentContainer.hasClass('notfixed')){
        contentContainer.removeClass('notfixed').addClass('fixed');

    }else if(contentContainer.hasClass('fixed')){
        contentContainer.removeClass('fixed').addClass('notfixed');
    };
});
Run Code Online (Sandbox Code Playgroud)

我发现这是一个足够简单的解决方案,适用于所有浏览器,并且也可以在便携式设备(即 iPhone、平板电脑等)上轻松使用。由于元素暂时固定,因此没有滚动:)

笔记!根据“contentContainer”元素的位置,您可能需要从左侧调整它。当固定类处于活动状态时,可以通过向该元素添加 css left 值来轻松完成此操作

contentContainer.css({
    'left': $(window).width() - contentContainer.width()/2 //This would result in a value that is the windows entire width minus the element we want to "center" divided by two (since it's only pushed from one side)
});
Run Code Online (Sandbox Code Playgroud)


Giu*_*lia 5

你可以这样做:

通过这种方式,您可以节省“微不足道”的内存,并且其中的元素Position: fixed不会移动,因此不会影响您的设计本身。

CSS(使用 CSS 让你的生活和记忆更轻松)

html[DisableScroll] {
    overflow-y: scroll;
}

html[DisableScroll] body {
    overflow-y: hidden;
    height: 100vh;
}
Run Code Online (Sandbox Code Playgroud)

JS

var enableScroll = function () {
   document.documentElement
     .removeAttribute('DisableScroll');
}
Run Code Online (Sandbox Code Playgroud)

例如

html[DisableScroll] {
    overflow-y: scroll;
}

html[DisableScroll] body {
    overflow-y: hidden;
    height: 100vh;
}
Run Code Online (Sandbox Code Playgroud)
var enableScroll = function () {
   document.documentElement
     .removeAttribute('DisableScroll');
}
Run Code Online (Sandbox Code Playgroud)
//When you want to enable escroll just call this function;

var enableScroll = function () {
   document.documentElement
   .removeAttribute('DisableScroll');
}
 
 setTimeout(() => {
    enableScroll();
}, 2000);
Run Code Online (Sandbox Code Playgroud)