jQuery 滚动DIV元素时如何防止页面滚动?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7600454/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent page scrolling when scrolling a DIV element?
提问by RIK
I have reviewed and tested the various functions for preventing the body ability to scroll whilst inside a div and have combined a function that should work.
我已经并测试了防止身体在 div 内滚动的各种功能,并结合了一个应该工作的功能。
$('.scrollable').mouseenter(function() {
$('body').bind('mousewheel DOMMouseScroll', function() {
return false;
});
$(this).bind('mousewheel DOMMouseScroll', function() {
return true;
});
});
$('.scrollable').mouseleave(function() {
$('body').bind('mousewheel DOMMouseScroll', function() {
return true;
});
});
- This is stopping all scrolling where as I want scrolling to still be possible inside the container
- This is also not deactivating on mouse leave
- 这将停止所有滚动,因为我希望在容器内仍然可以滚动
- 这也不会在鼠标离开时停用
Any ideas, or better ways of doing this?
任何想法或更好的方法来做到这一点?
回答by ?ime Vidas
Update 2:My solution is based on disabling the browser's native scrolling altogether (when cursor is inside the DIV) and then manually scrolling the DIV with JavaScript (by setting its .scrollTop
property). An alternative and IMO better approach would be to only selectively disable the browser's scrolling in order to prevent the page scroll, but not the DIV scroll. Check out Rudie's answer below which demonstrates this solution.
更新 2:我的解决方案基于完全禁用浏览器的本机滚动(当光标位于 DIV 内时),然后使用 JavaScript 手动滚动 DIV(通过设置其.scrollTop
属性)。另一种 IMO 更好的方法是仅选择性地禁用浏览器的滚动以防止页面滚动,而不是 DIV 滚动。查看下面展示此解决方案的 Rudie 的回答。
Here you go:
干得好:
$( '.scrollable' ).on( 'mousewheel DOMMouseScroll', function ( e ) {
var e0 = e.originalEvent,
delta = e0.wheelDelta || -e0.detail;
this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
e.preventDefault();
});
Live demo:https://jsbin.com/howojuq/edit?js,output
现场演示:https : //jsbin.com/howojuq/edit?js,output
So you manually set the scroll position and then just prevent the default behavior (which would be to scroll the DIV or whole web-page).
因此,您手动设置滚动位置,然后阻止默认行为(即滚动 DIV 或整个网页)。
Update 1:As Chris noted in the comments below, in newer versions of jQuery, the delta information is nested within the .originalEvent
object, i.e. jQuery does not expose it in its custom Event object anymore and we have to retrieve it from the native Event object instead.
更新 1:正如 Chris 在下面的评论中指出的那样,在较新版本的 jQuery 中,增量信息嵌套在.originalEvent
对象中,即 jQuery 不再在其自定义 Event 对象中公开它,而我们必须从本机 Event 对象中检索它.
回答by wojcikstefan
If you don't care about the compatibility with older IE versions (< 8), you could make a custom jQuery plugin and then call it on the overflowing element.
如果您不关心与旧 IE 版本(< 8)的兼容性,您可以制作一个自定义 jQuery 插件,然后在溢出元素上调用它。
This solution has an advantage over the one ?ime Vidas proposed, as it doesn't overwrite the scrolling behavior - it just blocks it when appropriate.
与 Vidas 提出的一种解决方案相比,该解决方案具有优势,因为它不会覆盖滚动行为——它只是在适当的时候阻止它。
$.fn.isolatedScroll = function() {
this.bind('mousewheel DOMMouseScroll', function (e) {
var delta = e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.detail,
bottomOverflow = this.scrollTop + $(this).outerHeight() - this.scrollHeight >= 0,
topOverflow = this.scrollTop <= 0;
if ((delta < 0 && bottomOverflow) || (delta > 0 && topOverflow)) {
e.preventDefault();
}
});
return this;
};
$('.scrollable').isolatedScroll();
回答by Rudie
I think it's possible to cancel the mousescroll event sometimes: http://jsfiddle.net/rudiedirkx/F8qSq/show/
我认为有时可以取消 mousescroll 事件:http: //jsfiddle.net/rudiedirkx/F8qSq/show/
$elem.on('wheel', function(e) {
var d = e.originalEvent.deltaY,
dir = d < 0 ? 'up' : 'down',
stop = (dir == 'up' && this.scrollTop == 0) ||
(dir == 'down' && this.scrollTop == this.scrollHeight-this.offsetHeight);
stop && e.preventDefault();
});
Inside the event handler, you'll need to know:
在事件处理程序中,您需要知道:
- scrolling direction
d = e.originalEvent.deltaY, dir = d < 0 ? 'up' : 'down'
because a positive number means scrolling down - scroll position
scrollTop
for top,scrollHeight - scrollTop - offsetHeight
for bottom
- 滚动方向,
d = e.originalEvent.deltaY, dir = d < 0 ? 'up' : 'down'
因为正数意味着向下滚动 scrollTop
顶部滚动位置,scrollHeight - scrollTop - offsetHeight
底部滚动
If you're
如果你是
- scrolling up, and
top = 0
, or - scrolling down, and
bottom = 0
,
- 向上滚动,和
top = 0
,或 - 向下滚动,然后
bottom = 0
,
cancel the event: e.preventDefault()
(and maybe even e.stopPropagation()
).
取消活动:(e.preventDefault()
甚至可能e.stopPropagation()
)。
I think it's better to not override the browser's scrolling behaviour. Only cancel it when applicable.
我认为最好不要覆盖浏览器的滚动行为。仅在适用时取消它。
It's probablt not perfectly xbrowser, but it can't be very hard. Maybe Mac's dual scroll direction is tricky though...
可能不是完美的xbrowser,但也不是很难。也许 Mac 的双滚动方向很棘手,但...
回答by Prasoon Kumar
Use below CSS property
overscroll-behavior: contain;
to child element
将下面的 CSS 属性
overscroll-behavior: contain;
用于子元素
回答by Vladimir Kuzmin
In the solution above there is a little mistake regarding Firefox. In Firefox "DOMMouseScroll" event has no e.detail property,to get this property you should write the following 'e.originalEvent.detail'.
在上面的解决方案中,关于 Firefox 有一个小错误。在 Firefox 中,“DOMMouseScroll”事件没有 e.detail 属性,要获得此属性,您应该编写以下“e.originalEvent.detail”。
Here is a working solution for Firefox:
这是 Firefox 的有效解决方案:
$.fn.isolatedScroll = function() {
this.on('mousewheel DOMMouseScroll', function (e) {
var delta = e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.originalEvent.detail,
bottomOverflow = (this.scrollTop + $(this).outerHeight() - this.scrollHeight) >= 0,
topOverflow = this.scrollTop <= 0;
if ((delta < 0 && bottomOverflow) || (delta > 0 && topOverflow)) {
e.preventDefault();
}
});
return this;
};
回答by I?aki Baz Castillo
here a simple solution without jQuery which does not destroy the browser native scroll (this is: no artificial/ugly scrolling):
这是一个没有 jQuery 的简单解决方案,它不会破坏浏览器本机滚动(这是:没有人工/丑陋的滚动):
var scrollable = document.querySelector('.scrollable');
scrollable.addEventListener('wheel', function(event) {
var deltaY = event.deltaY;
var contentHeight = scrollable.scrollHeight;
var visibleHeight = scrollable.offsetHeight;
var scrollTop = scrollable.scrollTop;
if (scrollTop === 0 && deltaY < 0)
event.preventDefault();
else if (visibleHeight + scrollTop === contentHeight && deltaY > 0)
event.preventDefault();
});
Live demo: http://jsfiddle.net/ibcaliax/bwmzfmq7/4/
回答by Alexandru Lighezan
A less hacky solution, in my opinion is to set overflow hidden on the body when you mouse over the scrollable div. This will prevent the body from scrolling, but an unwanted "jumping" effect will occur. The following solution works around that:
在我看来,一个不那么笨拙的解决方案是当您将鼠标悬停在可滚动 div 上时设置隐藏在正文上的溢出。这将阻止身体滚动,但会发生不需要的“跳跃”效果。以下解决方案可以解决这个问题:
jQuery(".scrollable")
.mouseenter(function(e) {
// get body width now
var body_width = jQuery("body").width();
// set overflow hidden on body. this will prevent it scrolling
jQuery("body").css("overflow", "hidden");
// get new body width. no scrollbar now, so it will be bigger
var new_body_width = jQuery("body").width();
// set the difference between new width and old width as padding to prevent jumps
jQuery("body").css("padding-right", (new_body_width - body_width)+"px");
})
.mouseleave(function(e) {
jQuery("body").css({
overflow: "auto",
padding-right: "0px"
});
})
You could make your code smarter if needed. For example, you could test if the body already has a padding and if yes, add the new padding to that.
如果需要,您可以使您的代码更智能。例如,您可以测试主体是否已经有填充,如果是,则添加新的填充。
回答by Ricardo Binns
see if this help you:
看看这是否对你有帮助:
demo: jsfiddle
演示:jsfiddle
$('#notscroll').bind('mousewheel', function() {
return false
});
edit:
编辑:
try this:
尝试这个:
$("body").delegate("div.scrollable","mouseover mouseout", function(e){
if(e.type === "mouseover"){
$('body').bind('mousewheel',function(){
return false;
});
}else if(e.type === "mouseout"){
$('body').bind('mousewheel',function(){
return true;
});
}
});
回答by David D
Here is my solution I've used in applications.
这是我在应用程序中使用的解决方案。
I disabled the body overflow and placed the entire website html inside container div's. The website containers have overflow and therefore the user may scroll the page as expected.
我禁用了正文溢出并将整个网站 html 放在容器 div 中。网站容器溢出,因此用户可能会按预期滚动页面。
I then created a sibling div (#Prevent) with a higher z-index that covers the entire website. Since #Prevent has a higher z-index, it overlaps the website container. When #Prevent is visible the mouse is no longer hovering the website containers, so scrolling isn't possible.
然后我创建了一个兄弟 div (#Prevent),它具有更高的 z-index 覆盖整个网站。由于#Prevent 具有更高的 z-index,它与网站容器重叠。当#Prevent 可见时,鼠标不再悬停在网站容器上,因此无法滚动。
You may of course place another div, such as your modal, with a higher z-index than #Prevent in the markup. This allows you to create pop-up windows that don't suffer from scrolling issues.
您当然可以在标记中放置另一个 div,例如您的模态,其 z-index 高于 #Prevent。这允许您创建不受滚动问题影响的弹出窗口。
This solution is better because it doesn't hide the scrollbars (jumping affect). It doesn't require event listeners and it's easy to implement. It works in all browsers, although with IE7 & 8 you have to play around (depends on your specific code).
此解决方案更好,因为它不会隐藏滚动条(跳跃效果)。它不需要事件监听器,而且很容易实现。它适用于所有浏览器,尽管在 IE7 和 8 中您必须玩弄(取决于您的特定代码)。
html
html
<body>
<div id="YourModal" style="display:none;"></div>
<div id="Prevent" style="display:none;"></div>
<div id="WebsiteContainer">
<div id="Website">
website goes here...
</div>
</div>
</body>
css
css
body { overflow: hidden; }
#YourModal {
z-index:200;
/* modal styles here */
}
#Prevent {
z-index:100;
position:absolute;
left:0px;
height:100%;
width:100%;
background:transparent;
}
#WebsiteContainer {
z-index:50;
overflow:auto;
position: absolute;
height:100%;
width:100%;
}
#Website {
position:relative;
}
jquery/js
jQuery/js
function PreventScroll(A) {
switch (A) {
case 'on': $('#Prevent').show(); break;
case 'off': $('#Prevent').hide(); break;
}
}
disable/enable the scroll
禁用/启用滚动
PreventScroll('on'); // prevent scrolling
PreventScroll('off'); // allow scrolling
回答by Ricky
I needed to add this event to multiple elements that might have a scrollbar. For the cases where no scrollbar was present, the main scrollbar didn't work as it should. So i made a small change to @?ime code as follows:
我需要将此事件添加到可能具有滚动条的多个元素中。对于不存在滚动条的情况,主滚动条无法正常工作。所以我对@?ime 代码做了一个小改动,如下所示:
$( '.scrollable' ).on( 'mousewheel DOMMouseScroll', function ( e ) {
if($(this).prop('scrollHeight') > $(this).height())
{
var e0 = e.originalEvent, delta = e0.wheelDelta || -e0.detail;
this.scrollTop += ( delta < 0 ? 1 : -1 ) * 30;
e.preventDefault();
}
});
Now, only elements with a scrollbar will prevent the main scroll from begin stopped.
现在,只有带有滚动条的元素才能阻止主滚动开始停止。