我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
当前回答
所选的答案是正确的,但有一些局限性:
用你的手指进行超硬的“投掷”仍然会在后台滚动<body> 在模态中点击<input>打开虚拟键盘将引导所有未来滚动到<body>
我没有解决第一个问题,但想对第二个问题有所了解。令人困惑的是,Bootstrap曾经记录了键盘问题,但他们声称已经修复,并引用http://output.jsbin.com/cacido/quiet作为修复的例子。
事实上,这个例子在我的iOS测试中运行良好。但是,将其升级到最新的Bootstrap (v4)会破坏它。
为了弄清楚它们之间的区别,我减少了一个测试用例,使其不再依赖于Bootstrap, http://codepen.io/WestonThayer/pen/bgZxBG。
决定因素很奇怪。避免键盘问题似乎要求没有在包含模态的根目录<div>上设置background-color,并且模态的内容必须嵌套在另一个<div>中,可以设置background-color。
要测试它,在Codepen示例中取消注释下面的行:
.modal {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 2;
display: none;
overflow: hidden;
-webkit-overflow-scrolling: touch;
/* UNCOMMENT TO BREAK */
/* background-color: white; */
}
其他回答
大多数解决方案都存在无法保留滚动位置的问题,所以我研究了Facebook是如何做到这一点的。除了将底层内容设置为position: fixed之外,他们还动态设置顶部以保留滚动位置:
scrollPosition = window.pageYOffset;
mainEl.style.top = -scrollPosition + 'px';
然后,当你再次移除覆盖时,你需要重置滚动位置:
window.scrollTo(0, scrollPosition);
我创建了一个小示例来演示这个解决方案
let overlayShown = false; let scrollPosition = 0; document.querySelector('.toggle').addEventListener('click', function() { if (!overlayShown) { showOverlay(); } else { removeOverlay(); } overlayShown = !overlayShown; }); function showOverlay() { scrollPosition = window.pageYOffset; const mainEl = document.querySelector('.main-content'); mainEl.style.top = -scrollPosition + 'px'; document.body.classList.add('show-overlay'); } function removeOverlay() { document.body.classList.remove('show-overlay'); window.scrollTo(0, scrollPosition); const mainEl = document.querySelector('.main-content'); mainEl.style.top = 0; } .main-content { background-image: repeating-linear-gradient( lime, blue 103px); width: 100%; height: 200vh; } .show-overlay .main-content { position: fixed; left: 0; right: 0; overflow-y: scroll; /* render disabled scroll bar to keep the same width */ /* Suggestion to put: overflow-y: hidden; Disabled scrolling still makes a mess with its width. Hiding it does the trick. */ } .overlay { display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.3); overflow: auto; } .show-overlay .overlay { display: block; } .overlay-content { margin: 50px; background-image: repeating-linear-gradient( grey, grey 20px, black 20px, black 40px); height: 120vh; } .toggle { position: fixed; top: 5px; left: 15px; padding: 10px; background: red; } /* reset CSS */ body { margin: 0; } <main class="main-content"></main> <div class="overlay"> <div class="overlay-content"></div> </div> <button class="toggle">Overlay</button>
一般来说,如果你想让父对象(在本例中是body)在子对象(在本例中是overlay)滚动时阻止它滚动,那么让子对象成为父对象的兄弟对象,以防止滚动事件冒泡到父对象。在父元素是body的情况下,这需要一个额外的包装元素:
<div id="content">
</div>
<div id="overlay">
</div>
使用浏览器的主滚动条滚动特定DIV内容以查看其工作情况。
值得注意的是,有时在body标签上添加"overflow:hidden"并不能完成这项工作。在这些情况下,您还必须将属性添加到html标记中。
html, body {
overflow: hidden;
}
当到达内容的顶部/底部时,CSS属性允许覆盖浏览器默认的溢出滚动行为。
只需添加以下样式叠加:
.overlay {
overscroll-behavior: contain;
...
}
Codepen演示
目前工作在Chrome, Firefox和IE(caniuse)
欲了解更多详细信息,请查看谷歌开发人员文章。
如果你想停止body/html滚动添加如下
CSS
html, body {
height: 100%;
}
.overlay{
position: fixed;
top: 0px;
left: 0px;
right: 0px;
bottom: 0px;
background-color: rgba(0, 0, 0, 0.8);
.overlay-content {
height: 100%;
overflow: scroll;
}
}
.background-content{
height: 100%;
overflow: auto;
}
HTML
<div class="overlay">
<div class="overlay-content"></div>
</div>
<div class="background-content">
lengthy content here
</div>
基本上,你不需要JS也能做到。
主要思想是添加html/body, height: 100%和overflow: auto。 在你的覆盖层中,你可以根据你的需要启用或禁用滚动。
希望这能有所帮助!