我一直在寻找一种“灯箱”型解决方案,允许这样但尚未找到一个(请提示,如果你知道的话)。
我正在尝试重新创建的行为就像您在点击图片时在Pinterest看到的那样。叠加层是可滚动的(,因为整个叠加层像页面顶部的页面一样向上移动)但是叠加层后面的 是固定的。
我尝试使用CSS(即整个页面顶部的div
叠加层和overflow: hidden
的正文来创建此内容,但它不会阻止{ {1}}可滚动。
如何防止正文/页面滚动但是在全屏容器内滚动?
答案 0 :(得分:560)
<强>理论强>
查看pinterest网站的当前实施(将来可能会更改),当您打开叠加层时,noscroll
类会应用于body
元素并设置overflow: hidden
,因此body
不再可滚动。
叠加层(即时创建或已在页面内部创建并通过display: block
显示,没有区别)有position : fixed
和overflow-y: scroll
,{{1} },top
,left
和right
属性设置为bottom
:此样式使叠加层填充整个视口。
叠加层中的0
只是在div
中,然后您看到的垂直滚动条与该元素相关。因此,内容是可滚动的,但叠加层仍然是固定的。
当你关闭缩放时,你隐藏了叠加层(通过position: static
),然后你也可以通过javascript(或者只是里面的内容,它取决于你如何注入它)完全删除它。
作为最后一步,您还必须将display: none
类删除到noscroll
(以便溢出属性返回其初始值)
<强>代码强>
(它可以通过更改叠加层的body
属性来显示和隐藏它并增加其可访问性。
<强>标记强>
(打开按钮)
aria-hidden
(叠加和关闭按钮)
<button type="button" class="open-overlay">OPEN LAYER</button>
<强> CSS 强>
<section class="overlay" aria-hidden="true">
<div>
<h2>Hello, I'm the overlayer</h2>
...
<button type="button" class="close-overlay">CLOSE LAYER</button>
</div>
</section>
Javascript (vanilla-JS)
.noscroll {
overflow: hidden;
}
.overlay {
position: fixed;
overflow-y: scroll;
top: 0; right: 0; bottom: 0; left: 0; }
[aria-hidden="true"] { display: none; }
[aria-hidden="false"] { display: block; }
最后,这是另一个示例,其中通过应用于var body = document.body,
overlay = document.querySelector('.overlay'),
overlayBtts = document.querySelectorAll('button[class$="overlay"]');
[].forEach.call(overlayBtts, function(btt) {
btt.addEventListener('click', function() {
/* Detect the button class name */
var overlayOpen = this.className === 'open-overlay';
/* Toggle the aria-hidden state on the overlay and the
no-scroll class on the body */
overlay.setAttribute('aria-hidden', !overlayOpen);
body.classList.toggle('noscroll', overlayOpen);
/* On some mobile browser when the overlay was previously
opened and scrolled, if you open it again it doesn't
reset its scrollTop property */
overlay.scrollTop = 0;
}, false);
});
属性的CSS transition
以淡入效果打开叠加层。此外,还应用opacity
以避免在滚动条消失时对基础文本进行重排。
<强> CSS 强>
padding-right
答案 1 :(得分:69)
如果你想防止在ios上过度滚动,你可以添加固定在.noscroll类的位置
body.noscroll{
position:fixed;
overflow:hidden;
}
答案 2 :(得分:37)
请勿在{{1}}上使用overflow: hidden;
。它会自动将所有内容滚动到顶部。也不需要JavaScript。利用body
。该解决方案甚至适用于移动Safari:
overflow: auto;
<div class="overlay">
<div class="overlay-content"></div>
</div>
<div class="background-content">
lengthy content here
</div>
<强>更新强>
对于想要键盘空格键,页面向上/向下工作的人:你需要专注于叠加层,例如点击它,或者在.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;
}
的这一部分响应之前手动JS聚焦它键盘。与覆盖“关闭”时相同,因为它只是将覆盖移动到侧面。除了浏览器,这些只是两个正常的div
,它不知道为什么它应该专注于它们中的任何一个。
答案 3 :(得分:30)
值得注意的是,有时在body标签中添加“overflow:hidden”并不能完成这项工作。在这些情况下,您还必须将属性添加到html标记中。
html, body {
overflow: hidden;
}
答案 4 :(得分:26)
大多数解决方案都存在不保留滚动位置的问题,所以我看看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 */
}
.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>
答案 5 :(得分:23)
overscroll-behavior
css属性允许在到达内容的顶部/底部时覆盖浏览器的默认溢出滚动行为。
只需将以下样式添加到叠加层:
.overlay {
overscroll-behavior: contain;
...
}
目前适用于Chrome,Firefox和IE(caniuse)
有关详细信息,请查看google developers article。
答案 6 :(得分:7)
所选答案是正确的,但有一些限制:
<body>
<input>
打开虚拟键盘会将所有未来的卷轴定向到<body>
我没有解决第一个问题,但想要了解第二个问题。令人困惑的是,Bootstrap曾经记录过键盘问题,但他们声称它已修复,引用http://output.jsbin.com/cacido/quiet作为修复的一个例子。
事实上,该示例在我的测试中适用于iOS。但是,将其升级到最新的Bootstrap(v4)会破坏它。
为了弄清楚它们之间的区别是什么,我将测试用例减少为不再依赖于Bootstrap,http://codepen.io/WestonThayer/pen/bgZxBG。
决定因素很奇怪。避免键盘问题似乎要求background-color
设置在包含模式的根<div>
上 模式的内容必须嵌套在另一个<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; */
}
答案 7 :(得分:6)
一般来说,如果您希望父项(在这种情况下是正文)在子项(在这种情况下为叠加层)滚动时阻止它滚动,则使子项成为父项的兄弟,以防止滚动事件发生冒泡到父母。如果父项是正文,则需要一个额外的包装元素:
<div id="content">
</div>
<div id="overlay">
</div>
请参阅Scroll particular DIV contents with browser's main scrollbar了解其工作情况。
答案 8 :(得分:4)
对于触摸设备,请尝试在叠加层的包装中添加1px宽,101vh
最小高度透明div。然后将-webkit-overflow-scrolling:touch; overflow-y: auto;
添加到包装器中。这使得移动游猎可以认为叠加是可滚动的,从而拦截了身体的触摸事件。
这是一个示例页面。在移动版游记中打开:http://www.originalfunction.com/overlay.html
https://gist.github.com/YarGnawh/90e0647f21b5fa78d2f678909673507f
答案 9 :(得分:3)
我发现这个问题试图解决我在Ipad和Iphone上的页面问题 - 当我将固定div显示为弹出图像时,正在滚动。
有些答案很好,但没有一个能解决我的问题。我找到了Christoffer Pettersson的博客文章。在那里提出的解决方案有助于我使用iOS设备的问题,它帮助我滚动背景问题。
Six things I learnt about iOS Safari's rubber band scrolling
因为有人建议我在博客文章中包含主要内容,以防链接过时。
&#34;为了禁用用户可以在&#34;菜单打开的情况下滚动背景页面&#34;,可以通过应用控制哪些元素应该被滚动?一些JavaScript和一个CSS类。
基于此Stackoverflow答案,您可以控制禁用滚动的元素不应该 触发touchmove事件时执行默认的滚动操作。&#34;
document.ontouchmove = function ( event ) {
var isTouchMoveAllowed = true, target = event.target;
while ( target !== null ) {
if ( target.classList && target.classList.contains( 'disable-scrolling' ) ) {
isTouchMoveAllowed = false;
break;
}
target = target.parentNode;
}
if ( !isTouchMoveAllowed ) {
event.preventDefault();
}
};
然后将禁用滚动类放在页面div上:
<div class="page disable-scrolling">
答案 10 :(得分:2)
您可以使用一些“新” css和JQuery轻松地做到这一点。
最初:body {... overflow:auto;}
使用JQuery,您可以在“覆盖”和“主体”之间动态切换。在“身体”上时,使用
body {
position: static;
overflow: auto;
}
在“覆盖”时使用
body {
position: sticky;
overflow: hidden;
}
jQuery的switch('body'->'overlay'):
$("body").css({"position": "sticky", "overflow": "hidden"});
jQuery的switch('overlay'->'body'):
$("body").css({"position": "static", "overflow": "auto"});
答案 11 :(得分:1)
使用以下HTML:
<body>
<div class="page">Page content here</div>
<div class="overlay"></div>
</body>
然后JavaScript拦截并停止滚动:
$(".page").on("touchmove", function(event) {
event.preventDefault()
});
然后让事情恢复正常:
$(".page").off("touchmove");
答案 12 :(得分:1)
我想添加之前的答案,因为我试图这样做,并且一旦我将身体切换到位置,一些布局就会破坏:修复。为了避免这种情况,我还必须将身体的高度设置为100%:
function onMouseOverOverlay(over){
document.getElementsByTagName("body")[0].style.overflowY = (over?"hidden":"scroll");
document.getElementsByTagName("html")[0].style.position = (over?"fixed":"static");
document.getElementsByTagName("html")[0].style.height = (over?"100%":"auto");
}
答案 13 :(得分:0)
如果要在移动设备/触摸设备上禁用,那么最简单的方法就是使用touch-action: none;
。
示例:
const app = document.getElementById('app');
const overlay = document.getElementById('overlay');
let body = '';
for (let index = 0; index < 500; index++) {
body += index + '<br />';
}
app.innerHTML = body;
app.scrollTop = 200;
overlay.innerHTML = body;
* {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
#app {
background: #f00;
position: absolute;
height: 100%;
width: 100%;
overflow-y: scroll;
line-height: 20px;
}
#overlay {
background: rgba(0,0,0,.5);
position: fixed;
top: 0;
left: 0;
right: 0;
height: 100%;
padding: 0 0 0 100px;
overflow: scroll;
}
<div id='app'></div>
<div id='overlay'></div>
(该示例在Stack Overflow的上下文中不起作用。您需要在独立页面中重新创建它。)
如果您想要停止滚动#app
容器,只需添加touch-action: none;
。
答案 14 :(得分:0)
尝试
var mywindow = $('body'), navbarCollap = $('.navbar-collapse');
navbarCollap.on('show.bs.collapse', function(x) {
mywindow.css({visibility: 'hidden'});
$('body').attr("scroll","no").attr("style", "overflow: hidden");
});
navbarCollap.on('hide.bs.collapse', function(x) {
mywindow.css({visibility: 'visible'});
$('body').attr("scroll","yes").attr("style", "");
});
答案 15 :(得分:0)
您要防止的行为称为滚动链接。要禁用它,请设置
6.1.4
在您的CSS叠加层上。
答案 16 :(得分:0)
如果要停止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,高度:100%,溢出:自动。 在叠加层内部,您可以根据需要启用/禁用滚动。
希望这会有所帮助!
答案 17 :(得分:-1)
就我而言,这些解决方案都没有在iPhone(iOS 11.0)上实现。
在我的所有设备上唯一有效的解决方案是这一个 - ios-10-safari-prevent-scrolling-behind-a-fixed-overlay-and-maintain-scroll-position
答案 18 :(得分:-2)
使用以下代码禁用和启用滚动条。
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();