我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
当前回答
当到达内容的顶部/底部时,CSS属性允许覆盖浏览器默认的溢出滚动行为。
只需添加以下样式叠加:
.overlay {
overscroll-behavior: contain;
...
}
Codepen演示
目前工作在Chrome, Firefox和IE(caniuse)
欲了解更多详细信息,请查看谷歌开发人员文章。
其他回答
试试这个
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", "");
});
如果有人正在寻找React函数组件的解决方案,你可以把它放在模态组件中:
useEffect(() => {
document.body.style.overflowY = 'hidden';
return () =>{
document.body.style.overflowY = 'auto';
}
}, [])
如果意图是禁用移动/触摸设备,那么最直接的方法是使用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;。
我想补充之前的答案,因为我试图这样做,一些布局打破了我切换到身体的位置:固定。为了避免这种情况,我还必须将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");
}
React功能组件的一个解决方案是使用useEffect钩子。
下面是下面的代码示例(请注意useEffect定义):
import {useEffect, useRef} from "react";
export default function PopoverMenu({className, handleClose, children}) {
const selfRef = useRef(undefined);
useEffect(() => {
const isPopoverOpenned = selfRef.current?.style.display !== "none";
const focusedElement = document?.activeElement;
const scrollPosition = {x: window.scrollX, y: window.scrollY};
if (isPopoverOpenned) {
preventDocBodyScrolling();
} else {
restoreDocBodyScrolling();
}
function preventDocBodyScrolling() {
const width = document.body.clientWidth;
const hasVerticalScrollBar = (window.innerWidth > document.documentElement.clientWidth);
document.body.style.overflowX = "hidden";
document.body.style.overflowY = hasVerticalScrollBar ? "scroll" : "";
document.body.style.width = `${width}px`;
document.body.style.position = "fixed";
}
function restoreDocBodyScrolling() {
document.body.style.overflowX = "";
document.body.style.overflowY = "";
document.body.style.width = "";
document.body.style.position = "";
focusedElement?.focus();
window.scrollTo(scrollPosition.x, scrollPosition.y);
}
return () => {
restoreDocBodyScrolling(); // cleanup on unmount
};
}, []);
return (
<>
<div
className="backdrop"
onClick={() => handleClose && handleClose()}
/>
<div
className={`pop-over-menu${className ? (` ${className}`) : ""}`}
ref={selfRef}
>
<button
className="pop-over-menu--close-button" type="button"
onClick={() => handleClose && handleClose()}
>
X
</button>
{children}
</div>
</>
);
}
最初发表于另一个相关的Stackoverflow问题:https://stackoverflow.com/a/69016517/14131330