【问题标题】:js/css : disable scrollbar but keep scroll positionjs/css : 禁用滚动条但保持滚动位置
【发布时间】:2012-09-03 20:42:09
【问题描述】:

我正在使用 Jquery 对话框在页面顶部打开一个弹出框窗口。 当我打开对话框时,我希望禁用常规页面滚动。 为此,我正在这样做:

$('body').css({overflow:'hidden'});

当对话框打开时,并且:

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

当对话框关闭时。

这可行,但是当滚动条被移除时,后面的内容会向右移动,结果并不好。

我尝试了另一种方法,通过创建一个 css 类“noscroll”,如下所示:

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

然后,我将在对话框打开/关闭时将此类添加和删除到正文中,而不是之前的 js 代码。

现在这适用于滚动条,后面的内容不会向右移动,但是使用这种方法,后面的内容会回到顶部。

所以基本上method1让内容向右移动,method2让内容回到顶部。

有人知道这个的解决方案吗?对话框打开时后面的内容没有滚动,禁用滚动也没有任何动作...?

【问题讨论】:

  • 您是否考虑过在对话框后面实现一个绝对定位的 100% div 覆盖以阻止与页面的所有交互?
  • 好想我会尝试并发布我的结果!
  • 你找到这个问题的解决方案了吗?你能帮助我吗?谢谢!对不起,我英语不好。
  • 不是真的,试试我用过的和人们建议的,看看什么最适合你...

标签: jquery css


【解决方案1】:

这是迄今为止我得到的最佳解决方案。相信我,我尝试了所有其他方法,这是我想出的最好和最简单的解决方案。它在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

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

【讨论】:

  • 看起来不错!您能否更新您的 Fiddle 链接,因为它不起作用
  • 更新了 JS Fiddle URL。
【解决方案2】:

我将这两个函数用于同一目的:

function enableBodyScroll() {
  if (document.readyState === 'complete') {
    document.body.style.position = '';
    document.body.style.overflowY = '';

    if (document.body.style.marginTop) {
      const scrollTop = -parseInt(document.body.style.marginTop, 10);
      document.body.style.marginTop = '';
      window.scrollTo(window.pageXOffset, scrollTop);
    }
  } else {
    window.addEventListener('load', enableBodyScroll);
  }
}

function disableBodyScroll({ savePosition = false } = {}) {
  if (document.readyState === 'complete') {
    if (document.body.scrollHeight > window.innerHeight) {
      if (savePosition) document.body.style.marginTop = `-${window.pageYOffset}px`;
      document.body.style.position = 'fixed';
      document.body.style.overflowY = 'scroll';
    }
  } else {
    window.addEventListener('load', () => disableBodyScroll({ savePosition }));
  }
}

它是如何工作的:

  1. 如果您想禁用滚动并保存当前位置,请运行disableBodyScroll({ savePosition: true })。

  2. 该功能检查页面是否加载(因为用户可能会在加载过程中触发对话框打开)。

  3. 如果页面被加载,它通过在body上设置margin-top来保存当前滚动位置,然后在其上设置position: fixed; overflow-y: scroll以移除滚动条。

  4. 如果页面没有加载,它会添加事件监听器以在页面加载时运行 (3.)。

为了启用滚动,一切都是一样的,但功能是删除样式而不是设置它们。

代码来源:https://github.com/funbox/diamonds/blob/master/lib/body-scroll.ts

【讨论】:

    【解决方案3】:

    我遇到了同样的问题,这个存储库帮助了我no-scroll

    【讨论】:

      【解决方案4】:

      记住偏移量应该可以避免弹出窗口;

      JSfiddle

      HTML

      <div id="popupholder">
          <button id="close">Close me</button>
      </div>
      
      
      asd <br />asd <br />asd <br />asd <br />asd <br />
      <button class="open">Popup</button>
      <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd<br />
      <button class="open">Popup</button>
      <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />
      <button class="open">Popup</button>
      <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd<br />
      <button class="open">Popup</button>
      <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />asd <br />
      

      CSS

      html, body {
          margin: 0px;
      }
      
      #popupholder {
          width: 100%;
          height: 100%;
          position: absolute;
          display: box;
          display: -webkit-box;
          display: -moz-box;
          background-color: rgba(0,0,0,0.75);
          display: none;
      }
      
      #close {
          display: block;
          height: 20px;
          margin: 75px auto 0px auto;
      }
      

      JavaScript

      $(document).ready(function() {
          $('.open').click(function() {
              // Block scrolling
              $('body').css('overflow', 'hidden');
      
              // Show popup
              var offset = window.pageYOffset;
              //console.log(offset);
              $('#popupholder').css({
                  'display': 'block',
                  'top': offset + 'px'
              });
          });
      
          $('#close').click(function() {
              // Enable scrolling
              $('body').css('overflow', 'auto');
      
              // Hide popup
              $('#popupholder').css('display', 'none');
          });
      });
      

      出于安全原因,您可以在您的#popupholder 中添加一个非常高的z-index,但这与问题无关。

      【讨论】:

      • 感谢您花时间编写代码,但我想禁用滚动条,而不是像 facebook 弹出窗口那样隐藏它。
      • 您也可以将overflow: hidden; 添加到#popupholder。否则,您可以查看 WebKit 的 ::-webkit-scrollbar { display: none; } 样式的类似变体。它将访问 Shadow DOM 并完全隐藏滚动条。
      【解决方案5】:

      我为我的解决方案做了一个非常简单的例子。

      http://jsfiddle.net/6eyJm/1/

      您的弹出窗口应该在一个框中

      <div id="shadow">
      <div id="popup">
          <a id='close' href="#">Close</a>
      </div>
      

      然后将这些 CSS 放在 de root div 上

      #shadow{
          display: none;
          position: fixed;
          top:0;
          bottom: 0;
          width: 100%;
          height:100%;
          background-color: rgba(0,0,0,0.6);
      }
      

      固定位置非常重要,因为您不想看到白色边框,它将占用整个窗口宽度而不是正文。

      然后是 JS 小技巧

      $('#open').click(function(e){
          e.preventDefault()
          $('body').width($('body').width());
          $('body').css('overflow', 'hidden');
          $('#shadow').css('display', 'block');
      })
      $('#close').click(function(e){
          e.preventDefault()
          $('body, #shadow').removeAttr('style')
      })
      

      这里的目标是在移除滚动条之前获取正文宽度。您的内容不会移动。

      希望对您有所帮助!

      对不起,我的英语不是我的母语。

      【讨论】:

      • 我打错字了,它不应该是 $('body #shadow').removeAttr 而是 $('body, #shadow').removeAttr(缺少昏迷)。
      • 当我把打开按钮放在列表中间,然后点击,页面滚动被禁用,但它会回到顶部。
      • 仍然无法正常工作。打开时,滚动位置保持在那里,但关闭时,它又回到顶部。我的代码在这里:http://jsfiddle.net/ZG8FU/
      • @TheatreOfSouls 锚链接正在滚动到页面顶部。阻止链接的默认行为:jsfiddle.net/zujv0g36.
      • 7 岁的帖子挽救了我的一天 :) 非常感谢你的想法,工作很愉快,老实说,我看不出你是英语的问题:D
      【解决方案6】:

      你可以计算溢出隐藏前后body宽度的差异,并将其作为padding-right应用到body

      var bodyStartW = $("body").width();
      $("body").css("overflow-y" , "hidden");
      var bodyEndW = $("body").width();
      var bodyMarginL = bodyEndW - bodyStartW;
      $("body").css("padding-right" , bodyMarginL);
      

      在 Safari 中,“html”标签也有同样的技巧,margin-right 而不是 padding-right

      【讨论】:

        猜你喜欢
        • 2015-05-31
        • 1970-01-01
        • 1970-01-01
        • 2011-10-22
        • 2011-03-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多