我想让我的身体在使用鼠标滚轮时停止滚动,而我的网站上的Modal(来自http://twitter.github.com/bootstrap)是打开的。
当模式被打开时,我试图调用下面的javascript片段,但没有成功
$(window).scroll(function() { return false; });
AND
$(window).live('scroll', function() { return false; });
请注意,我们的网站放弃了对IE6的支持,IE7+需要兼容。
这个解决方案对我很有效:
var scrollDistance = 0;
$(document).on("show.bs.modal", ".modal", function () {
scrollDistance = $(window).scrollTop();
$("body").css("top", scrollDistance * -1);
});
$(document).on("hidden.bs.modal", ".modal", function () {
$("body").css("top", "");
$(window).scrollTop(scrollDistance);
});
.content-area {
height: 750px;
background: grey;
text-align: center;
padding: 25px;
font-weight:700;
font-size: 30px;
}
body.modal-open {
position: fixed;
left: 0;
width: 100%;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/>
<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<div class="content-area">
Scroll Down To Modal Button<br/>
<svg xmlns="http://www.w3.org/2000/svg" width="56" height="56" fill="currentColor" class="bi bi-arrow-down" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 1a.5.5 0 0 1 .5.5v11.793l3.146-3.147a.5.5 0 0 1 .708.708l-4 4a.5.5 0 0 1-.708 0l-4-4a.5.5 0 0 1 .708-.708L7.5 13.293V1.5A.5.5 0 0 1 8 1z"/>
</svg>
</div>
<center class="my-3">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModal">
Launch demo modal
</button>
</center>
<div class="content-area"></div>
<!-- Modal -->
<div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p>
<p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary">Save changes</button>
</div>
</div>
</div>
</div>
基本上,当打开模态时,它会为主体添加一个负顶部,以在打开模态之前保持窗口滚动位置。关闭模态时,窗口滚动保持使用相同的值应用于顶部时,打开。
这种方法可以防止身体滚动。
这是一把能用的小提琴
大部分的片段都在这里,但我没有看到任何答案把它们放在一起。
这个问题有三个方面。
(1)防止底层页面滚动
$('body').css('overflow', 'hidden')
(2)并移除滚动条
var handler = function (e) { e.preventDefault() }
$('.modal').bind('mousewheel touchmove', handler)
(3)模态解散时进行清理
$('.modal').unbind('mousewheel touchmove', handler)
$('body').css('overflow', '')
如果模式不是全屏,那么将.modal绑定应用到全屏覆盖。
我读的大多数答案都是关于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>
</>
);
}
不能让它在Chrome上工作,只是通过改变CSS,因为我不想让页面滚动回顶部。这很有效:
$("#myModal").on("show.bs.modal", function () {
var top = $("body").scrollTop(); $("body").css('position','fixed').css('overflow','hidden').css('top',-top).css('width','100%').css('height',top+5000);
}).on("hide.bs.modal", function () {
var top = $("body").position().top; $("body").css('position','relative').css('overflow','auto').css('top',0).scrollTop(-top);
});
警告:下面的选项与Bootstrap v3.0无关。X,因为在这些版本中滚动被显式地限制在模态本身。如果禁用轮事件,可能会无意中阻止一些用户在高度大于视口高度的模态中查看内容。
还有另一个选择:车轮事件
滚动事件不可取消。但是,可以取消鼠标滚轮和滚轮事件。需要注意的是,并不是所有的传统浏览器都支持它们,Mozilla最近才在Gecko 17.0中添加了对后者的支持。我不知道它们的全部分布,但IE6+和Chrome确实支持它们。
下面是如何利用它们的方法:
$('#myModal')
.on('shown', function () {
$('body').on('wheel.modal mousewheel.modal', function () {
return false;
});
})
.on('hidden', function () {
$('body').off('wheel.modal mousewheel.modal');
});
JSFiddle