【问题标题】:How to programmatically disable page scrolling with jQuery如何使用 jQuery 以编程方式禁用页面滚动
【发布时间】:2011-04-09 01:37:07
【问题描述】:

使用 jQuery,我想禁用正文的滚动:

我的想法是:

  1. 设置body{ overflow: hidden;}
  2. 捕获当前scrollTop();/scrollLeft()
  3. 绑定到body滚动事件,设置scrollTop/scrollLeft为捕获的值。

有没有更好的办法?


更新:

请在http://jsbin.com/ikuma4/2/edit查看我的示例以及原因

我知道有人会想“他为什么不在面板上使用position: fixed?”。

请不要这样建议,因为我有其他原因。

【问题讨论】:

  • "有更好的方法吗?" - 除了让浏览器正常运行吗?
  • “戏剧性地”?
  • 也许是程序化的意思?因为它是 'programatically' 的 Firefox 顶级拼写更正建议
  • 这个线程正在运行\b\
  • @Sohnee 禁用滚动!== 错误

标签: jquery css scroll


【解决方案1】:

我发现这样做的唯一方法与您描述的类似:

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

【讨论】:

  • 请参阅jsbin.com/ikuma4/2/edit 并向我解释您的更好的任何理由?我是否遗漏了什么(我问是因为与我的示例相比,我看不出您的答案长度有任何原因)
  • 您的方法在 IE7 中不起作用。我也先尝试过。问题是它对滚动事件的反应不够快。它让文档滚动,然后当您的 JS 将滚动位置重置回您想要的位置时将其捕捉回来。
  • 另外,如果 body 溢出了 auto 以外的任何内容,它将被覆盖。我需要保留现有设置,这样也会增加一些开销。
  • 有谁知道为什么简单地用overflow: hidden 设计htmlbody 是不够的?我们最终仍然需要事件处理程序。
  • 这是一个绝妙的答案。要使其在触摸设备上运行,请查看this 答案。
【解决方案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。

如果您需要更多帮助,请在您所了解的地方发帖!

希望这有帮助。

【讨论】:

    【解决方案3】:

    你不能把身体高度设置为 100% 并隐藏溢出吗?见http://jsbin.com/ikuma4/13/edit

    【讨论】:

    • $("html").css({ height: '100%', overflow: 'hidden' });它很有效,谢谢阿德里安
    【解决方案4】:

    我在这里提出了一个可能有帮助的答案: jQuery simplemodal disable scrolling

    它展示了如何在不移动文本的情况下关闭滚动条。关于simplemodal的部分可以忽略。

    【讨论】:

      【解决方案5】:

      您可以使用此代码:

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

      【讨论】:

      • 您仍然可以使用鼠标中键滚动。
      • 不,这没关系,没有滚动!
      • 如果您使用一些额外的 css,您可以完全禁用滚动,请参阅我的回答了解更多详细信息。
      【解决方案6】:

      您可以使用可滚动的 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();
      }
      

      【讨论】:

      • 请不要使用“u”和“smth”之类的缩写。花点时间正确拼写,以提高可读性。
      【解决方案7】:

      我只是对tfe 的解决方案进行了一些调整。特别是,我添加了一些额外的控件,以确保当滚动条设置为 hidden 时,页面内容不会移动(又名 page shift)。

      可以分别定义两个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);
      }
      

      最后,注意一些可能的边距或填充的初始值。

      【讨论】:

      • 你的 javascript 中有错误 $body.css({'margin-right': 0, 'margin-bottom', 0});应该是 $body.css({'margin-right': 0, 'margin-bottom': 0});
      • 其实只要用marginRightmarginLeft :)
      【解决方案8】:

      对于有居中布局的人(通过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])
      

      …最后,.modal-noscroll 的 CSS…

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

      我敢说这比任何其他解决方案都更合适,但我还没有彻底测试它那个......:P


      编辑:请注意,我不知道这会在触摸设备上执行多糟糕(阅读:炸毁)。

      【讨论】:

        【解决方案9】:

        这将完全禁用滚动:

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

        恢复:

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

        在 Firefox 和 Chrome 上测试过。

        【讨论】:

        • 仍然在 chrome 上使用鼠标中键滚动。
        • 这会丢失当前的滚动位置。 OP 明确提到了捕获滚动位置,所以我认为他需要这样做。无论如何,我需要它,所以这对我来说用处有限
        • PS 省略 height: 100% 可以有效地将滚动锁定在当前位置而不会跳转 - 至少在最新的 Chrome 上是这样。
        • 这不是正确的答案。滚动位置未被捕获
        • 像魅力一样工作。这只是提醒'html'和'body'同样重要。
        【解决方案10】:

        我编写了一个 jQuery 插件来处理这个问题:$.disablescroll

        它可以防止从鼠标滚轮、触摸移动和按键事件中滚动,例如 Page Down

        有一个demo here

        用法:

        $(window).disablescroll();
        
        // To re-enable scrolling:
        $(window).disablescroll("undo");
        

        【讨论】:

        • 我尝试使用您的 disablescroll() 插件在听到 mouswheel/scroll 事件时暂时禁用滚动,但它不起作用。你有没有机会知道实现这种效果的方法?
        • @J.B.我可能可以提供帮助,但 cmets 不是最好的地方。加入我的堆栈溢出聊天,我会看看我能做什么:chat.stackoverflow.com/rooms/55043/disablescroll-usage
        • 很抱歉,这个插件甚至在你的 jsfiddle 中都不起作用。
        • 您可以告诉我它在哪个浏览器/平台上似乎无法运行,来帮助我检查一下?
        【解决方案11】:

        您也可以使用 DOM 来执行此操作。假设你有一个这样调用的函数:

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

        仅此而已!希望这对所有其他答案有所帮助!

        【讨论】:

          【解决方案12】:

          试试这个

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

          【讨论】:

          • 正是我想要的……几乎。无论如何要在箭头键期间禁用它?
          • @Cody - 将此与 css 溢出结合起来:隐藏
          • @cubbiu 怎么反转?
          • 你可以使用$('#element').off('scroll touchmove mousewheel');
          • 很好的解决方案。虽然您如何只禁用 body 滚动但允许在具有 overflow: scroll 的其他子元素中滚动?
          【解决方案13】:

          这就是我最终做的:

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

          【讨论】:

            【解决方案14】:

            不确定是否有人尝试过我的解决方案。这适用于整个 body/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的例子

            希望这个对某人有所帮助。

            【讨论】:

            • 这个可以正常工作,但有一个例外。当滚动被锁定时,我滚动,它有点抽搐,然后才真正锁定滚动......
            【解决方案15】:

            要关闭滚动试试这个:

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

            重置:

            $(window).off('scroll');
            

            【讨论】:

            • @EveryScreamer 不,它会让屏幕像疯了一样摇晃。试图找到解决方法。
            【解决方案16】:

            一个用于禁用滚动的衬里,包括鼠标中键。

            $(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 兼容性

            【讨论】:

              【解决方案17】:

              如果您只想禁用键盘导航滚动,您可以覆盖 keydown 事件。

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

              【讨论】:

                【解决方案18】:

                有人贴了这段代码,有恢复时不保留滚动位置的问题。原因是人们倾向于将它应用于 html 和 body 或只是 body 但它应该只应用于 html。这样在恢复滚动位置时将保持:

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

                恢复:

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

                【讨论】:

                • 不是'overflow': 'auto', 使用'overflow': 'initial',
                • @evtuhovdo 这就是我所缺少的。谢谢
                【解决方案19】:

                您可以将函数附加到滚动事件并阻止其默认行为。

                var $window = $(window);
                
                $window.on("mousewheel DOMMouseScroll", onMouseWheel);
                
                function onMouseWheel(e) {
                    e.preventDefault();
                }
                

                https://jsfiddle.net/22cLw9em/

                【讨论】:

                【解决方案20】:

                试试这个代码:

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

                【讨论】:

                  【解决方案21】:
                  • 隐藏卷轴:$("body").css("overflow", "hidden");
                  • 恢复卷轴:$("body").css("overflow", "initial");

                  【讨论】:

                    【解决方案22】:

                    我认为最好和干净的解决方案是:

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

                    那些事件监听器应该阻止滚动。 只需删除它们即可重新启用滚动

                    【讨论】:

                      【解决方案23】:

                      我正在使用以下代码来禁用滚动,它工作正常

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

                      除了在我的 android 平板电脑上,url 地址栏和顶部窗口标签仍然可见,当用户上下滚动时,窗口也会上下滚动大约 40px,并显示/隐藏 url 栏和标签。 有没有办法防止这种情况并完全禁用滚动?

                      【讨论】:

                        【解决方案24】:

                        如果想以编程方式禁用滚动,您可以使用:

                        overflow: clip;
                        

                        如果您想为用户禁用滚动,您可以使用:

                        overflow: hidden;
                        

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

                        overflow 属性的浏览器支持各不相同:

                        https://caniuse.com/?search=overflow

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2014-09-14
                          • 1970-01-01
                          • 1970-01-01
                          • 2020-05-25
                          • 2013-07-19
                          • 2019-05-15
                          • 2017-06-22
                          • 1970-01-01
                          相关资源
                          最近更新 更多