弹出窗口激活时禁用滚动

28

我按照一个在线教程 (http://uposonghar.com/popup.html) 创建了一个 jQuery 弹窗。

由于我对 jQuery 的了解较少,因此无法根据我的要求使其正常工作。

我的问题:

  1. 我希望在弹窗处于活动状态时禁用网页的滚动。
  2. 弹窗激活时背景淡出色在整个网页上不起作用。

CSS:

body {
    background: #999;
}
#ac-wrapper {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(255,255,255,.6);
    z-index: 1001;
}
#popup{
    width: 555px;
    height: 375px;
    background: #FFFFFF;
    border: 5px solid #000;
    border-radius: 25px;
    -moz-border-radius: 25px;
    -webkit-border-radius: 25px;
    box-shadow: #64686e 0px 0px 3px 3px;
    -moz-box-shadow: #64686e 0px 0px 3px 3px;
    -webkit-box-shadow: #64686e 0px 0px 3px 3px;
    position: relative;
    top: 150px; left: 375px;
}

JavaScript:

<script type="text/javascript">
function PopUp(){
    document.getElementById('ac-wrapper').style.display="none";
}
</script>

HTML:

<div id="ac-wrapper">
  <div id="popup">
  <center>
    <p>Popup Content Here</p>
    <input type="submit" name="submit" value="Submit" onClick="PopUp()" />
  </center>
  </div>
</div>

<p>Page Content Here</p>
9个回答

22
一个简单的答案,你可以使用并且不需要停止滚动事件的方法是将你的#ac-wrapper的位置设置为fixed。
例如:
#ac-wrapper {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(255,255,255,.6);
    z-index: 1001;
}

这将使弹出框的容器始终可见(顶部对齐-左侧),但仍允许滚动。

但是打开弹出框时滚动页面是不好的!!!(几乎总是如此)

不希望滚动的原因是,如果您的弹出框不是全屏或半透明,用户将看到弹出框后面的内容滚动。另外,当他们关闭弹出框时,他们现在将处于页面上的不同位置。

解决方案是,在javascript中绑定click事件以显示此弹出窗口时,还要向body添加一个类,其中包含这些规则:

.my-body-noscroll-class {
    overflow: hidden;
}

接下来,当通过触发某些操作或点击解散它来关闭弹出窗口时,您只需再次删除该类,即可在弹出窗口关闭后允许滚动。

如果用户在弹出窗口打开时滚动,文档将不会滚动。当用户关闭弹出窗口后,滚动将再次可用,用户可以继续之前的操作 :)


在现代的Chromium浏览器中,将overflow: hidden应用于<body>会移除垂直滚动条,并重绘整个页面以填充新创建的空间:/ - sKopheK
@sKopheK 是的,不幸的是没有什么合适的方法可以防止这种情况发生,也许你可以尝试使用vw单位来布局页面,而不是使用百分比宽度,但是这样滚动条可能会出现在右侧任何内容的顶部。如果您的弹出窗口有半透明的黑色背景,通常不会被注意到。此外,当您观看YouTube视频并使用汉堡菜单展开侧边栏时,就是这样做的 :) - SidOfc

21

禁用滚动条:

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

这将隐藏滚动条

背景淡入淡出:

我创建了自己的弹出对话框小部件,它也有一个背景。我使用了以下CSS:

div.modal{
    position: fixed;
    margin: auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 9998;
    background-color: #000;
    display: none;
    filter: alpha(opacity=25); /* internet explorer */
    -khtml-opacity: 0.25; /* khtml, old safari */
    -moz-opacity: 0.25; /* mozilla, netscape */
    opacity: 0.25; /* fx, safari, opera */
}

2
如果滚动条的位置在页面底部,这个解决方案就不起作用了...当模态框打开时,它会将全宽和高度从顶部设置为0;...所以当你关闭模态框时...你的页面会回到顶部,而不是你离开的地方! - DS_web_developer
这对我起作用了。但是我需要将类添加到我的HTML元素上,而不是在body上。此外,它在iOS上工作,但存在一个缺陷。一旦聚焦于我的弹出窗口中的表单,该类就不再起作用。奇怪。 - Garavani

6

我曾经遇到过类似的问题;当显示弹出式 div 时,希望禁用垂直滚动。

更改 body 的 overflow 属性确实可以解决问题,但也会影响文档的宽度。

我选择使用 jquery 来解决这个问题,并使用了一个占位符来代替滚动条。这样做并没有绑定到 scroll 事件,因此不会改变滚动条位置或引起闪烁 :)

HTML:

<div id="scrollPlaceHolder"></div>

CSS:

body,html
{
    height:100%; /*otherwise won't work*/
}
#scrollPlaceHolder
{
    height:100%;
    width:0px;
    float:right;
    display: inline;
    top:0;
    right: 0;
    position: fixed;
    background-color: #eee;
    z-index: 100;
}

Jquery:

function DisableScrollbar()
{
    // exit if page can't scroll
    if($(document).height() ==  $('body').height()) return;

    var old_width = $(document).width();
    var new_width = old_width;

    // ID's \ class to change
    var items_to_change = "#Banner, #Footer, #Content";

    $('body').css('overflow-y','hidden');

    // get new width
    new_width = $(document).width()

    // update width of items to their old one(one with the scrollbar visible)
    $(items_to_change).width(old_width);

    // make the placeholder the same width the scrollbar was
    $("#ScrollbarPlaceholder").show().width(new_width-old_width);

    // and float the items to the other side.
    $(items_to_change).css("float", "left");

}

function EnableScrollbar()
{
    // exit if page can't scroll
    if ($(document).height() ==  $('body').height()) return;   

    // remove the placeholder, then bring back the scrollbar
    $("#ScrollbarPlaceholder").fadeOut(function(){          
        $('body').css('overflow-y','auto');
    });
}

希望这能帮到您。

如果滚动条的位置在页面底部,这个解决方案就不起作用了...当模态框打开时,它会将全宽和高度从顶部设置为0;...所以当你关闭模态框时...你的页面会回到顶部,而不是你离开的地方! - DS_web_developer
我喜欢这种防止布局移位的尝试,但是不同的浏览器和操作系统使用不同的宽度/颜色,在macOS的情况下,滚动条被覆盖并且在不活动时是不可见的(因此只有在滚动时才能看到)。你已经解决了一个浏览器或者可能是一个操作系统上的所有浏览器的问题,但这并不是普遍适用的 :) - SidOfc

4

如果简单地切换页面的 'overflow-y' 属性会破坏您的页面滚动位置,请尝试使用以下 2 个函数(jQuery):

// Run this function when you open your popup:
var disableBodyScroll = function(){
    window.body_scroll_pos = $(window).scrollTop(); // write page scroll position in a global variable
    $('body').css('overflow-y','hidden');
}

// Run this function when you close your popup:
var enableBodyScroll = function(){
    $('body').css('overflow-y','scroll');
    $(window).scrollTop(window.body_scroll_pos); // restore page scroll position from the global variable
}

3

使用下面的代码禁用和启用滚动条。

 Scroll = (
    function(){
          var x,y;
         function hndlr(){
            window.scrollTo(x,y);
            //return;
          }  
          return {

               disable : function(x1,y1){
                    x = x1;
                    y = y1;
                   if(window.addEventListener){
                       window.addEventListener("scroll",hndlr);
                   } 
                   else{
                        window.attachEvent("onscroll", hndlr);
                   }     

               },
               enable: function(){
                      if(window.removeEventListener){
                         window.removeEventListener("scroll",hndlr);
                      }
                      else{
                        window.detachEvent("onscroll", hndlr);
                      }
               } 

          }
    })();
 //for disabled scroll bar.
Scroll.disable(0,document.body.scrollTop);
//for enabled scroll bar.
Scroll.enable();

1

https://jsfiddle.net/satishdodia/L9vfhdwq/1/
HTML:- 打开弹出窗口

弹出窗口

点击打开弹出窗口后,滚动条会停止,当点击关闭后,滚动条会自动运行。

关闭

**css:-**    
        #popup{
        position: fixed;
        background: rgba(0,0,0,.8);
        display: none;
        top: 20px;
        left: 50px;
        width: 300px;
        height: 200px;
        border: 1px solid #000;
        border-radius: 5px;
        padding: 5px;
        color: #fff;
    } 
**jquery**:-
       <script type="text/javascript">
        $("#open_popup").click(function(){
        $("#popup").css("display", "block");
        $('body').css('overflow', 'hidden');
      });

      $("#close_popup").click(function(){
        $("#popup").css("display", "none");
        $('body').css('overflow', 'scroll');
      }); 
      </script>

太好了,正是我想要的。只需要简单的JS。谢谢 :) - Marc

0

我曾经遇到同样的问题,并找到了解决方法,你只需要在弹出元素上停止touchmove事件的传播即可。对我来说,这是全屏菜单出现在屏幕上时无法滚动的问题,现在已经可以了。

$(document).on("touchmove","#menu-left-toggle",function(e){
    e.stopPropagation();
});

0

这个解决方案对我有效。

HTML:

<div id="payu-modal" class="modal-payu">

      <!-- Modal content -->
      <div class="modal-content">
        <span class="close">&times;</span>
        <p>Some text in the Modal..</p>
      </div>

    </div>

CSS:

.modal-payu {
  display: none; /* Hidden by default */
  position: fixed; /* Stay in place */
  z-index: 1; /* Sit on top */
  padding-top: 100px; /* Location of the box */
  left: 0;
  bottom: 0;


  width: 100%; /* Full width */
  height: 100%; /* Full height */
  overflow: auto; /* Enable scroll if needed */
  background-color: rgb(0,0,0); /* Fallback color */
  background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}

/* Modal Content */
.modal-content {
  background-color: #fefefe;
  margin: auto;
  padding: 20px;
  border: 1px solid #888;
  width: 80%;
}

/* The Close Button */
.close {
  color: #aaaaaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
}

.close:hover,
.close:focus {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}

JS:

<script>
      var btn = document.getElementById("button_1");
      btn.onclick = function() {
        modal.style.display = "block";
        $('html').css('overflow', 'hidden');
      }

    var span = document.getElementsByClassName("close")[0];
    var modal = document.getElementById('payu-modal');

    window.onclick = function(event) {
      if (event.target != modal) {
      }else{
        modal.style.display = "none";
        $('html').css('overflow', 'scroll');
      }
    }

    span.onclick = function() {
      modal.style.display = "none";
      $('html').css('overflow', 'scroll');
    }

    </script>

0



我遇到了问题并尝试了几种解决方案, 这篇文章解决了我的问题(https://css-tricks.com/prevent-page-scrolling-when-a-modal-is-open/),而且非常简单!

它使用了“固定主体”解决方案,这在许多帖子中很常见。 这个解决方案的问题是,当弹出窗口关闭时,主体将滚动回顶部。 但是该文章指出:通过在使用解决方案时操纵CSS top和position属性,我们可以恢复滚动位置。

解决方案的另一个问题是,您无法在多个弹出窗口场景中应用解决方案。 因此,我添加了一个变量来存储弹出窗口的计数,以确保程序不会在错误的时间触发初始化过程或重置过程。

这就是我得到的最终解决方案:

// freeze or free the scrolling of the body:

const objectCountRef = { current: 0 }

function freezeBodyScroll () {
  if (objectCountRef.current === 0) {  // trigger the init process when there is no other popup exist
    document.body.style.top = `-${window.scrollY}px`
    document.body.style.position = 'fixed'
  }
  objectCountRef.current += 1
}
function freeBodyScroll () {
  objectCountRef.current -= 1
  if (objectCountRef.current === 0) {  // trigger the reset process when all the popup are closed
    const scrollY = document.body.style.top
    document.body.style.position = ''
    document.body.style.top = ''
    window.scrollTo(0, parseInt(scrollY || '0') * -1)
  }
}

您也可以在我的Codepen上查看演示:https://codepen.io/tabsteveyang/pen/WNpbvyb

编辑


更多关于“固定主体”解决方案的信息

该方法主要是将body元素的CSS position属性设置为“fixed”,使其无法滚动。 无论它滚动了多远,当body被固定时,它将滚动回到顶部,这是我不希望看到的行为。(想象一下用户正在浏览长内容,几乎滚动到页面底部,突然弹出一个弹窗,使页面立即滚动回到顶部,这是一个糟糕的用户体验)

文章中的解决方案

基于“固定主体”的方法,此解决方案还将body的CSS top设置为“-window.scrollY px”的值,使body看起来像停留在当前滚动位置而又被固定。 此外,该解决方案使用body的CSS top作为临时参考,以便我们在想要再次使body可滚动时通过该属性检索滚动位置。(请注意,您必须将获取的位置乘以-1才能使其为正数)


请提供您答案的解释,以便下一个用户知道为什么这个解决方案对您有效。此外,总结您的答案,以防链接在未来停止工作。 - Elydasian

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接