我想让我的身体在使用鼠标滚轮时停止滚动,而我的网站上的Modal(来自http://twitter.github.com/bootstrap)是打开的。
当模式被打开时,我试图调用下面的javascript片段,但没有成功
$(window).scroll(function() { return false; });
AND
$(window).live('scroll', function() { return false; });
请注意,我们的网站放弃了对IE6的支持,IE7+需要兼容。
/* =============================
* Disable / Enable Page Scroll
* when Bootstrap Modals are
* shown / hidden
* ============================= */
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault)
e.preventDefault();
e.returnValue = false;
}
function theMouseWheel(e) {
preventDefault(e);
}
function disable_scroll() {
if (window.addEventListener) {
window.addEventListener('DOMMouseScroll', theMouseWheel, false);
}
window.onmousewheel = document.onmousewheel = theMouseWheel;
}
function enable_scroll() {
if (window.removeEventListener) {
window.removeEventListener('DOMMouseScroll', theMouseWheel, false);
}
window.onmousewheel = document.onmousewheel = null;
}
$(function () {
// disable page scrolling when modal is shown
$(".modal").on('show', function () { disable_scroll(); });
// enable page scrolling when modal is hidden
$(".modal").on('hide', function () { enable_scroll(); });
});
Bootstrap的模态在模态对话框显示时自动将类modal-open添加到主体,并在对话框隐藏时将其删除。因此,您可以在CSS中添加以下内容:
body.modal-open {
overflow: hidden;
}
你可能会说上面的代码属于Bootstrap CSS代码库,但这是一个简单的修复,可以将它添加到你的网站。
2013年2月8日更新
这在Twitter Bootstrap v. 2.3.0中已经停止工作——他们不再向主体添加modal-open类。
一个变通的方法是在模态即将显示时将类添加到主体中,并在模态关闭时将其删除:
$("#myModal").on("show", function () {
$("body").addClass("modal-open");
}).on("hidden", function () {
$("body").removeClass("modal-open")
});
2013年3月11日更新
看起来modal-open类将在Bootstrap 3.0中返回,显式地用于防止滚动:
在body上重新引入。modal-open(这样我们就可以把滚动移到这里)
看这个:https://github.com/twitter/bootstrap/pull/6342 -看Modal部分。
我有一个边栏,是由复选框黑客生成的。
但主要思想是保存文档scrollTop,而不是在滚动窗口期间更改它。
我只是不喜欢页面跳转时,身体变成'溢出:隐藏'。
window.addEventListener('load', function() {
let prevScrollTop = 0;
let isSidebarVisible = false;
document.getElementById('f-overlay-chkbx').addEventListener('change', (event) => {
prevScrollTop = window.pageYOffset || document.documentElement.scrollTop;
isSidebarVisible = event.target.checked;
window.addEventListener('scroll', (event) => {
if (isSidebarVisible) {
window.scrollTo(0, prevScrollTop);
}
});
})
});
我读的大多数答案都是关于React的。
我的React功能组件的最佳解决方案是使用@arcticmatt最初提供的解决方案
我在下面的代码示例中包含了一些在其他答案中提到的改进(注意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>
</>
);
}
因为对我来说,这个问题主要出现在iOS上,所以我提供了只在iOS上修复的代码:
if(!!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform)) {
var $modalRep = $('#modal-id'),
startScrollY = null,
moveDiv;
$modalRep.on('touchmove', function(ev) {
ev.preventDefault();
moveDiv = startScrollY - ev.touches[0].clientY;
startScrollY = ev.touches[0].clientY;
var el = $(ev.target).parents('#div-that-scrolls');
// #div-that-scrolls is a child of #modal-id
el.scrollTop(el.scrollTop() + moveDiv);
});
$modalRep.on('touchstart', function(ev) {
startScrollY = ev.touches[0].clientY;
});
}