如何暂时禁用滚动?

Posted

技术标签:

【中文标题】如何暂时禁用滚动?【英文标题】:How to disable scrolling temporarily? 【发布时间】:2011-06-13 18:58:55 【问题描述】:

我正在使用 scrollTo jQuery 插件,想知道是否可以通过 javascript 暂时禁用窗口元素的滚动?我想禁用滚动的原因是,当您在 scrollTo 动画时滚动时,它会变得非常丑陋;)

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

【问题讨论】:

如果它仍然显示,那么用户被训练认为它必须在运行。如果剂量没有移动或没有响应,那么它将破坏用户对您的页面如何工作的心理模型并导致混乱。我只想找到一种更好的方法来处理动画时的滚动,例如停止动画。 另一种解决方案:***.com/questions/9280258/… 【参考方案1】:

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

window.onscroll = function ()  window.scrollTo(0, 0); ;

在 IE6 中有点跳动。

【讨论】:

不是真正的禁用,更像是尝试滚动时的默认设置。 @Marcus 与不可取消的活动一样好。 尽管它并没有真正禁用它,但它会模拟它,这对我来说已经足够了。 恕我直言-最佳答案在这里。另外,您不必将其锁定为(0, 0),只需使用当前滚动位置即可。 但是我们如何重新启用它呢?【参考方案2】:

scroll 事件无法取消。但是您可以通过取消这些交互事件来做到这一点:鼠标 & 触摸滚动与滚动相关的按钮

[Working demo]

// 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.preventDefault();


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


// modern Chrome requires  passive: false  when adding event
var supportsPassive = false;
try 
  window.addEventListener("test", null, Object.defineProperty(, 'passive', 
    get: function ()  supportsPassive = true;  
  ));
 catch(e) 

var wheelOpt = supportsPassive ?  passive: false  : false;
var wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

// call this to Disable
function disableScroll() 
  window.addEventListener('DOMMouseScroll', preventDefault, false); // older FF
  window.addEventListener(wheelEvent, preventDefault, wheelOpt); // modern desktop
  window.addEventListener('touchmove', preventDefault, wheelOpt); // mobile
  window.addEventListener('keydown', preventDefaultForScrollKeys, false);


// call this to Enable
function enableScroll() 
  window.removeEventListener('DOMMouseScroll', preventDefault, false);
  window.removeEventListener(wheelEvent, preventDefault, wheelOpt); 
  window.removeEventListener('touchmove', preventDefault, wheelOpt);
  window.removeEventListener('keydown', preventDefaultForScrollKeys, false);

更新:修复了带有被动监听器的 Chrome 桌面和现代移动浏览器

【讨论】:

对陷入此陷阱的其他开发者的提示:请确保从其他 jQuery 尝试停止滚动的尝试中删除任何和所有 'e.stopPropagation()' 调用,因为它不仅不起作用,它防止事件冒泡到这个有效的代码。希望我浪费的 30 分钟能帮助别人节省时间:) 您可以将 32(空格)添加到禁用的键数组(在代码 cmets 中显示)。 我可以像往常一样滚动这个:使用中键按下并移动鼠标......因此这个技巧不会影响像我这样的用户;) 滚动条没有被禁用。 我仍然可以通过将文件拖到页面顶部/底部来使其滚动。这也可以通过选择页面上的文本并在顶部/底部进行相同的拖动来实现。【参考方案3】:

很抱歉回答一个旧帖子,但我正在寻找解决方案并遇到了这个问题。

对于这个问题有很多解决方法来仍然显示滚动条,比如给容器一个 100% 的高度和一个 overflow-y: scroll 样式。

在我的例子中,我刚刚创建了一个带有滚动条的 div,我在将 overflow: hidden 添加到正文时显示它:

function disableScroll() 
    document.getElementById('scrollbar').style.display = 'block';
    document.body.style.overflow = 'hidden';

元素滚动条必须有这样的样式:

overflow-y: scroll; top: 0; right: 0; display: none; height: 100%; position: fixed;

这显示了一个灰色的滚动条,希望对以后的访问者有所帮助。

【讨论】:

【参考方案4】:

结合 sdleihssirhc 的想法,我找到了一个更好但有问题的方法:

window.onscroll = function() 
    window.scrollTo(window.scrollX, window.scrollY);
    //Or
    //window.scroll(window.scrollX, window.scrollY);
    //Or Fallback
    //window.scrollX=window.scrollX;
    //window.scrollY=window.scrollY;
;

我没有测试它,但我稍后会编辑并让大家知道。我 85% 确定它适用于主流浏览器。

【讨论】:

需要将window.scrollX和window.scrollY的旧值存储在函数外才能冻结滚动,否则没用!【参考方案5】:

只需在正文中添加一个类即可:

.stop-scrolling 
  height: 100%;
  overflow: hidden;

当你想重新启用滚动时,添加类然后删除,在 IE、FF、Safari 和 Chrome 中测试。

$('body').addClass('stop-scrolling')

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

$('body').bind('touchmove', function(e)e.preventDefault())

并取消绑定以重新启用滚动。在 ios6 和 android 2.3.3 中测试

$('body').unbind('touchmove')

【讨论】:

知道了!您必须像处理$('body').bind('touchmove', function(e)e.preventDefault()) 一样处理touchmove 事件。编辑此答案以包含此移动解决方案。 酷,只需要确保任何内部滚动都可以在触摸设备的模式下工作。可以在模态下方做一个覆盖,并防止覆盖而不是正文上的默认触摸移动。 虽然此解决方案确实有效,但它具有(可能)不受欢迎的效果,即滚动回页面顶部。 这对我不起作用,除非我的选择器是 $('body,html') 此解决方案有效,但当您将此类应用于正文(例如)时,滚动条消失并创建“凹凸”效果(在窗口操作系统下)【参考方案6】:

这个怎么样? (如果你使用 jQuery)

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

window.onscroll = function() 
    var overlay = $body.children(".ui-widget-overlay").first();

    // Check if the overlay is visible and restore the previous scroll state
    if (overlay.is(":visible")) 
        var scrollPos = $body.data("scroll-pos") ||  x: 0, y: 0 ;
        window.scrollTo(scrollPos.x, scrollPos.y);
    
    else 
        // Just store the scroll state
        $body.data("scroll-pos",  x: $window.scrollLeft(), y: $window.scrollTop() );
    
;

【讨论】:

有点跳跃,但这适用于 IE 7(客户端使用它)。其他解决方案没有。【参考方案7】:

我在另一个 site 上找到了这个答案:

禁用滚动:

$( ".popup").live(
    popupbeforeposition: function(event, ui) 
    $("body").on("touchmove", false);

);

关闭弹窗后释放滚动:

$( ".popup" ).live(
    popupafterclose: function(event, ui) 
    $("body").unbind("touchmove");

);

【讨论】:

这似乎只是停止触摸滚动,但鼠标滚动、箭头键、上下翻页键等仍然有效。 -1 这些“事件”用于触摸滚动,只需替换您需要的任何事件。 另外,这似乎用于其他一些非常具体的情况。位置前弹出?那应该是为了什么?这与暂时禁用滚动有什么关系?至少让它与这种情况相关。看起来你是直接从网站上复制的。【参考方案8】:

根据您希望使用已移除的滚动条实现的目标,您可以只修复要从中移除滚动条的元素(在点击时,或您想要暂时停用滚动条的任何其他触发器)

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

开课

.fixed
    position: fixed;

然后使用 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');
    ;
);

我发现这是一个足够简单的解决方案,适用于所有浏览器,并且可以在便携式设备(即 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)
);

【讨论】:

【参考方案9】:

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

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


function enable_scroll() 
   ...
   document.ontouchmove = function(e) 
     return true; 
   

【讨论】:

你确定这是一个答案而不仅仅是其他答案的评论吗?【参考方案10】:

另一种解决方案:

body 
    overflow-y: scroll;
    width: 100%;
    margin: 0 auto;

这样你总是有一个垂直滚动条,但由于我的大部分内容都比视口长,这对我来说没问题。内容以一个单独的 div 居中,但如果没有在正文中再次设置边距,我的内容将保留在左侧。

这是我用来显示弹出窗口/模态的两个函数:

var popup_bodyTop = 0;
var popup_bodyLeft = 0;

function popupShow(id)

    $('#'+ id).effect('fade');
    $('#popup-overlay').effect('fade');

    // remember current scroll-position
    // because when setting/unsetting position: fixed to body
    // the body would scroll to 0,0
    popup_bodyLeft = $(document).scrollLeft();
    popup_bodyTop  = $(document).scrollTop();

    // invert position
    var x = - popup_bodyLeft;
    var y = - popup_bodyTop;

    $('body').css('position', 'fixed');
    $('body').css('top', y.toString() +'px');
    $('body').css('left', x.toString() +'px');


function popupHide(id)

    $('#'+ id).effect('fade');
    $('#popup-overlay').effect('fade');
    $('body').css('position', '');
    $('html, body').scrollTop(popup_bodyTop);
    $('html, body').scrollLeft(popup_bodyLeft);

结果:由于左侧滚动条,背景不可滚动且内容无法重新定位。使用当前的 FF、Chrome 和 IE 10 测试。

【讨论】:

这对我有用,并且在使用 position:fixed 后滚动到顶部的问题。谢谢你!【参考方案11】:

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

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

Demo here.

On github here.

/**
 * $.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);

【讨论】:

很高兴它很有用。注意我用link to this in jQuery plugin format编辑过。 如果禁用滚动按钮确实有效,可能会有所帮助 @user1672694,它在 Chrome 中工作。你的浏览器是什么,你在哪个演示页面上发现了这个错误?控制台中是否有 JS 错误? 在 Chrome(38,Windows 7)上,我仍然可以通过单击并按住中间按钮然后拖动来滚动。 请忽略,我发现绑定mousewheel很有魅力【参考方案12】:

您可以阻止空格键滚动并隐藏浏览器滚动条:

$(document).keydown(function(event) 
    if (event.keyCode == 32) 
        return false;

    
);

document.documentElement.style.overflow = 'hidden';
document.body.scroll = 'no';

【讨论】:

禁用空格键确实是不行的解决方案【参考方案13】:

我知道这是一个老问题,但我不得不做一些非常相似的事情,经过一段时间寻找答案并尝试不同的方法后,我最终使用了一个非常简单的解决方案。

我的问题非常相似,几乎相同,唯一的区别是我不必实际显示滚动条 - 我只需要确保它的宽度仍然可以使用,所以页面的宽度不会改变,而我覆盖显示。

当我开始将叠加层滑入屏幕时,我会这样做:

$('body').addClass('stop-scrolling').css('margin-right', 8);

在我将叠加层滑出屏幕后,我会这样做:

$('body').removeClass('stop-scrolling').css('margin-right', 0);

重要提示:这非常有效,因为当visible 时,我的叠加层位于absoluteright: 0px

【讨论】:

【参考方案14】:

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

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


function enableScrolling()
    window.onscroll=function();

【讨论】:

Jumpy 在 Safari 7.1 和 IE 11 中。最新的 Chrome、Firefox、Opera ok。 在最新的 Chrome 上还是有点紧张 工作正常,在 safari、chrome 中,但在 IE 中闪烁 如果此解决方案不适用于某些浏览器,那就是浏览器问题 可以设置window.onscroll=null而不是添加一个空的匿名函数,nullwindow.onload的初始值【参考方案15】:

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

CSS

.scrollDisabled    
    position: fixed;
    margin-top: 0;// override by JS to use acc to curr $(window).scrollTop()
    width: 100%;

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

【讨论】:

如果我将 overflow-y: scroll 添加到 .scrollDisabled 样式中,我发现这对我有用。否则,每次滚动条隐藏时都会有一点跳跃。当然,这只对我有用,因为我的页面足够长,即使在最大的显示器上也需要滚动条。【参考方案16】:

galambalazs 的解决方案很棒!它在 Chrome 和 Firefox 中都非常适合我。它还可以扩展以防止浏览器窗口出现任何默认事件。 假设您正在画布上做一个应用程序。你可以这样做:

var events = 
  preventDefault: function(e) 
    e = e || window.event;
    if (e.preventDefault) e.preventDefault();
    e.returnValue = false;  
  ,

  //spacebar: 32, pageup: 33, pagedown: 34, end: 35, home: 36,
  //left: 37, up: 38, right: 39, down: 40
  keys: [32, 33, 34, 35, 36, 37, 38, 39, 40],
  keydown: function(e) 
    for (var i = events.keys.length; i--;) 
      if (e.keyCode === events.keys[i]) 
        events.preventDefault(e);
        return;
      
    
  ,

  wheel: function(e) 
    events.preventDefault(e);
  ,

  disable: function() 
    if (window.addEventListener) 
      window.addEventListener('DOMMouseScroll', events.wheel, false);
    
    window.onmousewheel = document.onmousewheel = events.wheel;
    document.onkeydown = helpers.events.keydown;
  ,

  enable: function() 
    if (window.removeEventListener) 
      window.removeEventListener('DOMMouseScroll', events.wheel, false);
    
    window.onmousewheel = document.onmousewheel = document.onkeydown = null;  
  

然后在您的应用程序上,假设您要处理自己的事件,如鼠标、键盘、触摸事件等...您可以在鼠标进入画布时禁用默认事件并重新启用它们当鼠标熄灭时:

function setMouseEvents(canvas) 
  var useCapture = false;

  //Mouse enter event
  canvas.addEventListener('mouseenter', function(event) 
    events.disable();
  , useCapture);

  //Mouse leave event
  canvas.addEventListener('mouseleave', function(event) 
    events.enable();
  , useCapture);

您甚至可以使用此 hack 禁用右键菜单:

function disableRightClickMenu(canvas) 
  var my_gradient = canvas.context.createLinearGradient(0, 0, 0, 225);
  my_gradient.addColorStop(0, "white");
  my_gradient.addColorStop(1, "white");
  canvas.context.fillStyle = my_gradient;
  canvas.context.fillRect(0, 0, canvas.width, canvas.height);
  canvas.oncontextmenu = function()  return false; ;

【讨论】:

【参考方案17】:

使用 JavaScript 启用以下 CSS 会有所帮助。我不如这里的其他人,但这对我有用。

body 
    position: fixed;
    overflow-y: scroll;

【讨论】:

所以基于我的答案得到了赞成票,但我的答案只有反对票?为什么 *** 讨厌我?【参考方案18】:

在尝试使用 jquery 的 animate 命令为 div 设置动画时,我在移动屏幕上遇到了类似的动画问题,但在笔记本电脑上没有。所以我决定使用一个计时器来频繁地恢复窗口的滚动位置,以至于在肉眼看来文档看起来是静止的。该解决方案在三星 Galaxy-2 或 iphone-5 等小屏幕移动设备上运行良好。

此方法的主要逻辑:设置窗口滚动位置到原始滚动位置的计时器应该在jquery animate命令之前启动,然后当动画完成时我们需要清除这个计时器(@ 987654321@ 是动画开始前的位置)。

令我惊喜的是,如果计时器间隔为 1 millisecond,则该文档实际上在动画期间显示为静态,这正是我的目标。

//get window scroll position prior to animation
//so we can keep this position during animation
var xPosition = window.scrollX || window.pageXOffset || document.body.scrollLeft;
var yPosition = window.scrollY || window.pageYOffset || document.body.scrollTop;

//NOTE:restoreTimer needs to be global variable
//start the restore timer
restoreTimer = setInterval(function() 
    window.scrollTo(xPosition, yPosition);
, 1);

//animate the element emt
emt.animate(
    left: "toggle",
    top: "toggle",
    width: "toggle",
    height: "toggle"
, 500, function() 
    //when animation completes, we stop the timer
    clearInterval(restoreTimer);
);

另一个有效的解决方案:根据 Mohammad Anini 在这篇文章下启用/禁用滚动的回答,我还发现修改后的代码版本如下。

//get current scroll position
var xPosition = window.scrollX || window.pageXOffset || document.body.scrollLeft;
var yPosition = window.scrollY || window.pageYOffset || document.body.scrollTop;

//disable scrolling
window.onscroll = function() 
    window.scrollTo(xPosition, yPosition);
;

//animate and enable scrolling when animation is completed
emt.animate(
    left: "toggle",
    top: "toggle",
    width: "toggle",
    height: "toggle"
, 500, function() 
    //enable scrolling when animation is done
    window.onscroll = function() ;
);

【讨论】:

【参考方案19】:

我对这个问题的看法还包括对正文宽度的关注,因为当我们用overflow = "hidden" 隐藏滚动条时,页面似乎会跳动一点。 以下代码非常适合我,并且基于 Angular 方法。

element.bind('mouseenter', function() 
    var w = document.body.offsetWidth;
    document.body.style.overflow = 'hidden';
    document.body.style.width = w + 'px';
);

element.bind('mouseleave', function() 
    document.body.style.overflow = 'initial';
    document.body.style.width = 'auto';
);

【讨论】:

【参考方案20】:

一个对我有用的简单解决方案(暂时禁用窗口滚动)。

基于这个小提琴:http://jsfiddle.net/dh834zgw/1/

以下 sn-p (使用 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;
 

现在当你移除modal时,别忘了移除html标签上的noscroll类:

$('html').toggleClass('noscroll');

【讨论】:

【参考方案21】:

我使用 showModalDialog,将辅助页面显示为模式对话框。

隐藏主窗口滚动条:

document.body.style.overflow = "hidden";

当关闭模态对话框时,显示主窗口滚动条:

document.body.style.overflow = "scroll";

从对话框访问主窗口中的元素:

parent.document.getElementById('dialog-close').click();

仅适用于任何搜索showModalDialog的人:(在原始代码的第 29 行之后)

document.getElementById('dialog-body').contentWindow.dialogArguments = arg;
document.body.style.overflow = "hidden";//****
document.getElementById('dialog-close').addEventListener('click', function(e) 
    e.preventDefault();
    document.body.style.overflow = "scroll";//****
    dialog.close();
);

【讨论】:

这在 React 中对我有用,其中 jQuery 不存在并且 React 无权管理 body 标签的状态。【参考方案22】:

在我看来,取消已接受答案中的事件是一种可怕的方法:/

我在下面使用了position: fixed; top: -scrollTop();

演示:https://jsfiddle.net/w9w9hthy/5/

来自我的 jQuery 弹出项目:https://github.com/seahorsepip/jPopup

//Freeze page content scrolling
function freeze() 
    if($("html").css("position") != "fixed") 
        var top = $("html").scrollTop() ? $("html").scrollTop() : $("body").scrollTop();
        if(window.innerWidth > $("html").width()) 
            $("html").css("overflow-y", "scroll");
        
        $("html").css("width": "100%", "height": "100%", "position": "fixed", "top": -top);
    


//Unfreeze page content scrolling
function unfreeze() 
    if($("html").css("position") == "fixed") 
        $("html").css("position", "static");
        $("html, body").scrollTop(-parseInt($("html").css("top")));
        $("html").css("position": "", "width": "", "height": "", "top": "", "overflow-y": "");
    

此代码考虑了宽度、高度、滚动条和页面跳转问题。

以上代码解决的可能问题:

宽度,当设置位置固定时,html元素宽度可以小于100% 高度,同上 滚动条,当设置位置固定时,页面内容不再有滚动条,即使它在导致水平页面跳转之前有滚动条也是如此 pagejump,当设置位置固定时,页面scrollTop不再有效导致垂直页面跳转

如果有人对上述页面冻结/解冻代码有任何改进,请告诉我,以便我可以将这些改进添加到我的项目中。

【讨论】:

【参考方案23】:

我刚刚整理的一些东西:

jsfiddle

document.onwheel = function(e) 
  // get the target element
  target = e.target;
  // the target element might be the children of the scrollable element
  // e.g., "li"s inside an "ul", "p"s inside a "div" etc.
  // we need to get the parent element and check if it is scrollable
  // if the parent isn't scrollable, we move up to the next parent
  while (target.scrollHeight <= target.clientHeight) 
    // while looping parents, we'll eventually reach document.body
    // since body doesn't have a parent, we need to exit the while loop
    if (target == document.body) 
      break;
    
    target = target.parentElement;
  
  // we want this behaviour on elements other than the body
  if (target != document.body) 
    // if the scrollbar is at the top and yet if it still tries to scroll up
    // we prevent the scrolling
    if (target.scrollTop <= 0 && e.deltaY < 0) 
      e.preventDefault();
    
    // similarly, if the scrollbar is at the bottom and it still tries to scroll down
    // we prevent it
    else if (target.clientHeight + target.scrollTop >= target.scrollHeight && e.deltaY > 0) 
      e.preventDefault();
    
  
;
body 
  background: gainsboro;


#box 
  width: 300px;
  height: 600px;
  padding: 5px;
  border: 1px solid silver;
  margin: 50px auto;
  background: white;
  overflow: auto;
<div id="box">
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
  <p>
    Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor
    in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
  </p>
</div>

【讨论】:

【参考方案24】:

基于夏安福布斯的回答,以及我通过 fcalderan 在这里找到的回答:Just disable scroll not hide it? 并修复 Hallodom 的滚动条消失问题

CSS:

.preventscroll
    position: fixed;
    overflow-y:scroll;

JS:

whatever.onclick = function()
    $('body').addClass('preventscroll');

whatevertoclose.onclick = function()
    $('body').removeClass('preventscroll');

此代码确实会将您跳转到页面顶部,但我认为 fcalderan 的代码有一个解决方法。

【讨论】:

【参考方案25】:

从 Chrome 56 和其他现代浏览器开始,您必须将 passive:false 添加到 addEventListener 调用才能使 preventDefault 工作。所以我用它来停止在移动设备上滚动:

function preventDefault(e)
    e.preventDefault();


function disableScroll()
    document.body.addEventListener('touchmove', preventDefault,  passive: false );

function enableScroll()
    document.body.removeEventListener('touchmove', preventDefault,  passive: false );

【讨论】:

【参考方案26】:

我也有同样的问题,下面是我的处理方式。

/* file.js */
var body = document.getElementsByTagName('body')[0];
//if window dont scroll
body.classList.add("no-scroll");
//if window scroll
body.classList.remove("no-scroll");

/* file.css */
.no-scroll
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;

希望对您有所帮助。

【讨论】:

【参考方案27】:

最简单的方法是:

$("body").css("overflow", "hidden"); // Remove the scroll bar temporarily

要撤消它:

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

易于实施,但唯一的缺点是:

如果页面居中(水平),页面会向左跳一点。

这是由于滚动条被移除,并且视口变宽了一些。

【讨论】:

将重置滚动位置 @AngelDavidCalderaroPacciott 不,滚动位置将保持相同的高度/距离。 @Daan 它确实重置了 Chrome 上的滚动位置 @Tom 我刚刚检查过它,它只在某些情况下才会这样做(当身高与其孩子无关时)。请尝试将body 改为html 我打赌你没有在 Iphone 中检查你的解决方案,因为 overflow:hidden 在那里不起作用【参考方案28】:

这是我停止滚动的解决方案(没有 jQuery)。当侧面菜单出现时,我用它来禁用滚动。

<button onClick="noscroll()" style="position:fixed; padding: 8px 16px;">Disable/Enable scroll</button>
<script>
var noscroll_var;
function noscroll()
  if(noscroll_var)
    document.getElementsByTagName("html")[0].style.overflowY = "";
    document.body.style.paddingRight = "0";
    noscroll_var = false
  else
    document.getElementsByTagName("html")[0].setAttribute('style', 'overflow-y: hidden !important');
    document.body.style.paddingRight = "17px";
    noscroll_var = true
  
/*noscroll()*/
</script>

<!-- Just to fill the page -->
<script>
  for(var i=0; i <= 80; i++)
    document.write(i + "<hr>")
  
</script>

我放了 17px 的 padding-right 来补偿滚动条的消失。但这也是有问题的,主要是针对移动浏览器。根据this获取条宽即可解决。

All together in this Pen.

【讨论】:

【参考方案29】:

我在触控设备上遇到了类似的问题。向元素添加“touch-action: none”解决了这个问题。

了解更多信息。看看这个:-

https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action

【讨论】:

【参考方案30】:

这是迄今为止我得到的最简单的解决方案。相信我,我尝试了所有其他方法,这是最简单的。它在Windows 设备 上运行良好,从右侧推动页面为系统滚动条和 IOS 设备留出空间,这些设备在浏览器中的滚动条不需要空间.因此,通过使用它,您不需要在右侧添加填充,这样当您使用 css 隐藏 body 或 html 的溢出时页面不会闪烁

如果您考虑一下,解决方案非常简单。这个想法是在打开弹出窗口的那一刻给 window.scrollTop() 相同的确切位置。当窗口调整大小时也改变那个位置(一旦发生滚动位置就会改变)。

所以我们开始...

首先让我们创建一个变量,让您知道弹出窗口已打开,并将其命名为 stopWindowScroll。如果我们不这样做,您将在您的页面上收到未定义变量的错误并将其设置为 0 - 未激活。

$(document).ready(function()
    stopWindowScroll = 0;
);

现在让打开的弹出函数可以是代码中的任何函数,它可以触发您作为插件或自定义使用的任何弹出窗口。在这种情况下,它将是一个简单的自定义弹出窗口,带有一个简单的文档点击功能。

$(document).on('click','.open-popup', function()
    // Saving the scroll position once opening the popup.
    stopWindowScrollPosition = $(window).scrollTop();
    // Setting the stopWindowScroll to 1 to know the popup is open.
    stopWindowScroll = 1;
    // Displaying your popup.
    $('.your-popup').fadeIn(300);
);

接下来我们要做的是创建关闭弹出功能,我再次重复一遍,它可以是您已经创建或正在插件中使用的任何功能。重要的是我们需要这 2 个函数将 stopWindowScroll 变量设置为 1 或 0 以了解它何时打开或关闭。

$(document).on('click','.open-popup', function()
    // Setting the stopWindowScroll to 0 to know the popup is closed.
    stopWindowScroll = 0;
    // Hiding your popup
    $('.your-popup').fadeOut(300);
);

然后让我们创建 window.scroll 函数,这样我们就可以在上面提到的 stopWindowScroll 设置为 1 时阻止滚动。

$(window).scroll(function()
    if(stopWindowScroll == 1) 
         // Giving the window scrollTop() function the position on which
         // the popup was opened, this way it will stay in its place.
         $(window).scrollTop(stopWindowScrollPosition);
    
);

就是这样。除了您自己的页面样式外,无需任何 CSS 即可工作。这对我来说就像一个魅力,我希望它可以帮助你和其他人。

这是一个关于 JSFiddle 的工作示例:

JS Fiddle Example

如果这有帮助,请告诉我。问候。

【讨论】:

以上是关于如何暂时禁用滚动?的主要内容,如果未能解决你的问题,请参考以下文章

禁用 UIScrollView 手势

禁用列表视图中的滚动

如何判断屏幕保护程序是不是暂时禁用?

如何暂时禁用 d3.js 中的缩放

如何使用 Python 暂时禁用键盘输入

如何使用 JavaScript 暂时禁用文本选择?