防止从元素到窗口滚动冒泡

IT技术 javascript jquery html events scroll
2021-01-30 14:38:50

我有一个包含 iframe 的模式框窗口(弹出窗口),
在该iframe 内有一个可滚动div

当我滚动 iframe 的内部 DIV 并且它已达到其上限或下限时,
浏览器本身的窗口开始滚动。这是一种不受欢迎的行为

我已经尝试过这样的事情,
当鼠标进入弹出框区域时,它会在onMouseEnter 时杀死主窗口滚动

e.preventDefault() 由于某种原因无法正常工作......

$("#popup").mouseenter(function(){
   $(window).bind("scroll", function(e){
        e.preventDefault();
   }); 
}).mouseleave(function(){
    $(window).unbind("scroll");
});

更新

好像现在 2013 年e.preventDefault();就够了……

6个回答

抱歉,据我所知,无法取消任何类型的滚动事件。

无论W3MSDN说:

Cancelable  No
Bubbles     No

我认为您必须将其留给浏览器作者来解决。Firefox(无论如何在 Linux 上为 3.5)对我来说似乎有更好的行为:如果在您开始使用滚轮的那一刻孩子已经在顶部/底部,它只会滚动父级

对于较旧的 IE,您必须采取不同的方式。stackoverflow.com/questions/1000597/...否则,请记住您是在窗口上阻止它。
2021-03-16 14:38:50
@FlavorScape 怎么样?event.preventDefault() 是否适用于滚动事件?MSDN 另有说法...
2021-03-22 14:38:50
现在可以在 chrome 和 FF 中取消事件。
2021-03-31 14:38:50
根据您的布局,您可以将容器设置为 position:fixed,当鼠标进入可滚动目标时,将其重置为鼠标离开可滚动目标时的状态。但请记住,触摸设备不能悬停。
2021-04-05 14:38:50
它可以做到——而且相对容易:stackoverflow.com/questions/5802467/...
2021-04-07 14:38:50

使用简单的 CSS 属性解决(对于某些浏览器):
overscroll-behavior

auto 默认的滚动溢出行为正常发生。

包含 在设置此值的元素内部观察到默认滚动溢出行为(例如“反弹”效果或刷新),但相邻滚动区域不会发生滚动链接,例如底层元素不会滚动。

相邻滚动区域不会发生滚动链接,并防止默认滚动溢出行为。

body{
  height: 600px;
  overflow: auto;
}

section{
  width: 50%;
  height: 50%;
  overflow: auto;
  background: lightblue;
  overscroll-behavior: none; /*   <--- the trick    */
}

section::before{
  content: '';
  height: 200%;
  display: block;
}
<section>
 <input value='end' />
</section>

只需在滚动应该“锁定”到的元素上应用该样式属性,滚动事件就不会冒泡到任何可能也有滚动的父元素。


与上面相同的演示,但没有技巧:

适用于具有足够高度以触发正在呈现的滚动条的元素。但是对于没有那么高的同一个类的元素,它们仍然冒泡了滚动事件!也试图为此找到解决方案。
2021-03-16 14:38:50
在边缘 18. 有没有人可以提供其他东西?
2021-03-24 14:38:50
惊人的!感谢您提供出色的解决方案。
2021-03-28 14:38:50
查看有关浏览器兼容性的更多信息:caniuse.com/?search=overscroll-behavior
2021-04-02 14:38:50
overscroll-behavior可以成为救命稻草。不幸的是,Safari 尚不支持它。
2021-04-10 14:38:50

如果我们不能阻止窗口滚动,为什么不撤消它呢?即捕获滚动事件,然后滚动回固定位置。

只要悬停在 上,以下代码就会锁定 Y 轴$("#popup")

// here we store the window scroll position to lock; -1 means unlocked
var forceWindowScrollY = -1;

$(window).scroll(function(event) {
  if(forceWindowScrollY != -1 && window.scrollY != forceWindowScrollY) {
    $(window).scrollTop(forceWindowScrollY);    
  }
});

$("#popup").hover(function() {
  if(forceWindowScrollY == -1) {
    forceWindowScrollY = $(window).scrollTop();
  }
}, function() {
  forceWindowScrollY = -1;
});

我将它用于http://bundestube.de/上的查询建议框 (在顶部搜索框中输入一些字符以使可滚动窗格可见):

截屏

这在 Chrome/Safari (Webkit) 中完美运行,在 Firefox 和 Opera 中存在一些滚动故障。出于某种原因,它不适用于我的 IE 安装。我想这与 jQuery 的悬停方法有关,该方法似乎在 100% 的情况下都无法正常工作。

真奇怪。在我的 Mac (10.6.6) 上完美运行。我们说的是同一件事吗?为清楚起见,我添加了屏幕截图。仅当鼠标指针位于建议框上方时,窗口的滚动条才会被禁用。
2021-03-14 14:38:50
@zaius 太好了,它对您有用。是的,向上滚动是按原样设计的。我使用了一个额外的“if(window.scrollY > forceWindowScrollY)”条件。
2021-03-17 14:38:50
啊对不起 - 我试图在结果页面上的框中滚动。是的,这现在对我有用。干得好!不知道是不是故意的,但它似乎也没有抓住向上滚动。
2021-03-24 14:38:50
@zaius 你能再试一次吗?
2021-04-08 14:38:50
我尝试了你的网站,但它不适用于 Mac 上的 Chrome/Firefox/Safari
2021-04-12 14:38:50

我知道这是一个很老的问题,但由于这是谷歌的顶级结果之一......我不得不以某种方式取消没有jQuery的滚动冒泡,这段代码对我有用:

function preventDefault(e) {
  e = e || window.event;
  if (e.preventDefault)
    e.preventDefault();
  e.returnValue = false;  
}

document.getElementById('a').onmousewheel = function(e) { 
  document.getElementById('a').scrollTop -= e. wheelDeltaY; 
  preventDefault(e);
}
@vsync 当然它不起作用,因为您示例中的 iframe 是跨域的,并且您无法在跨域 iframe 上获取滚动事件和内容。
2021-04-13 14:38:50

我的 jQuery 插件:

$('.child').dontScrollParent();

$.fn.dontScrollParent = function()
{
    this.bind('mousewheel DOMMouseScroll',function(e)
    {
        var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail;

        if (delta > 0 && $(this).scrollTop() <= 0)
            return false;
        if (delta < 0 && $(this).scrollTop() >= this.scrollHeight - $(this).height())
            return false;

        return true;
    });
}
似乎,至少this.on('mousewheel DOMMouseScroll', function(){})部分(注意on而不是bind
2021-04-05 14:38:50