我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
当前回答
如果有人正在寻找React函数组件的解决方案,你可以把它放在模态组件中:
useEffect(() => {
document.body.style.overflowY = 'hidden';
return () =>{
document.body.style.overflowY = 'auto';
}
}, [])
其他回答
大多数解决方案都存在无法保留滚动位置的问题,所以我研究了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的高度设置为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");
}
如果你想在ios上防止过度滚动,你可以在你的.noscroll类中添加位置固定
body.noscroll{
position:fixed;
overflow:hidden;
}
使用下面的代码禁用和启用滚动条。
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();
你可以用一些“新”css和JQuery轻松做到这一点。
初始:body{…溢出:汽车;} 使用JQuery,你可以在“overlay”和“body”之间动态切换。当使用“body”时,使用
body {
position: static;
overflow: auto;
}
在“叠加”时使用
body {
position: sticky;
overflow: hidden;
}
JQuery for switch('body'->'overlay'):
$("body").css({"position": "sticky", "overflow": "hidden"});
JQuery for switch('overlay'->'body'):
$("body").css({"position": "static", "overflow": "auto"});