我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
我一直在寻找一个“灯箱”类型的解决方案,允许这一点,但还没有找到一个(请建议,如果你知道任何)。
我试图重现的行为就像你在Pinterest上点击图片时看到的一样。覆盖层是可滚动的(整个覆盖层向上移动,就像一页在一页的顶部),但覆盖层后面的主体是固定的。
我试图用CSS创建这个(即一个div覆盖在整个页面和身体溢出:隐藏),但它不阻止div是可滚动的。
如何保持主体/页面从滚动,但保持滚动在全屏容器内?
当前回答
要防止的行为称为滚动链接。要禁用它,请设置
overscroll-behavior: contain;
在你的CSS覆盖。
其他回答
使用以下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”);
我想补充之前的答案,因为我试图这样做,一些布局打破了我切换到身体的位置:固定。为了避免这种情况,我还必须将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");
}
就我而言,这些解决方案都不适用于iPhone (iOS 11.0)。
在我的所有设备上唯一有效的修复是这个- ios-10-safari-prevent-scroll -behind-a-fixed-overlay-and-maintain-scroll-position
不要使用overflow: hidden;在身体。它会自动将所有内容滚动到顶部。也不需要JavaScript。利用溢出:auto;。这个解决方案甚至适用于移动Safari:
HTML结构
<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;
}
在这里可以看到演示和源代码。
更新:
对于想要键盘空格键的人,page up/down工作:你需要专注于覆盖,例如,点击它,或手动JS聚焦在它之前,这部分div将响应键盘。当覆盖层被“关闭”时也是一样,因为它只是将覆盖层移动到一边。否则对浏览器来说,这只是两个正常的div,它不知道为什么它应该关注其中的任何一个。
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