$(window).scroll() 无法触发滚动条事件
问题描述
页面添加一个返回顶部的按钮(fixed),并监控窗口的 scroll 滚动事件。当 scrollTop(滚动条距离顶部的距离,及文档滚动距离)在一定范围内(比如视窗高度)隐藏返回顶部按钮;当 scrollTop 超过一定高度,则显示返回顶部按钮。
具体 demo
<div id="back-to-top">
<img src="./images/back-to-top.png" width="50" height="50" alt="返回顶部">
</div>
<style type="text/css">
/*返回顶部*/
#back-to-top{
position: fixed;
right:20px;
bottom:100px;
z-index: 1;
display: none;
}
</style>
<script type="text/javascript">
//返回顶部
$(function(){
$(window).scroll(function(){
if ($(window).scrollTop() > 300){
$("#back-to-top").fadeIn(500);
} else {
$("#back-to-top").fadeOut(500);
}
});
$("#back-to-top").click(function(){
$('body,html').animate({
scrollTop: 0
}, 800);
});
});
</script>
代码添加到现有页面后发现,$(window).scroll()
并未触发。这是 jQuery 的 scroll 绑定事件写法,JavaScript 版本如下:
window.onscroll = function(){
}
使用 Javascript 给 window 添加 onscroll 事件也不成功,说明跟 jQuery 版本无关。
浏览器里 Event Listeners 视窗下,scroll 事件下是存在 Window 这一绑定对象的,说明事件绑定成功。
将 demo 单独页面测试,运行正常,说明 demo 代码本身也没有问题。
解决方法
百度关键词 jquery 绑定 window scroll 事件回调失败
,找到一些 scroll 无法触发的解决方案。
其中有一个说因为 html 和 body 宽、高被设置成了 100%,所以无法触发 scroll 事件。demo 测试发现这是不对的。只要文档的高度大于视窗的高度,scroll 事件就可以触发。宽、高与屏幕宽高完全一致的情况下,确实无法触发,但这种情况下也不需要去监控 scroll 事件。demo 测试还发现 $(window).scrollTop()
是随着页面滚动而变化的,$('body').scrollTop()
始终为 0。
[notice]window
、'html'
和 'body'
三个对象中,html 绑定 scroll 事件是无法触发的;window
对象没有 s
,不加引号;'body'
绑定是需要加引号的。正常情况下,window 的 scrollTop 值随页面滚动变化,body 的 scrollTop 始终为0;当 overflow:auto
时,body 的 scrollTop 值随页面滚动变化,而 window 的 scrollTop 始终为 0。[/notice]
最终找到了问题的关键点:CSS 的 overflow 与 window.onscroll 发生了冲突。
demo 中默认是未设置 overflow 属性的,而目标页面上 overflow:auto
。demo 测试重现了这个 bug,说明问题就出在了 overflow 属性上。因为 overflow:auto
时页面是能够正常滚动的,所以并未发觉异常。
测试发现,html 或 body 的 overflow 属性值为 auto/scroll(hidden 都滚不动了,肯定没法触发,不讨论)时,window 的 scoll 滚动事件无法触发。但是,当 overflow 为 auto/scroll 时,将 scroll 绑定在 body 上是可以正常触发的。
综上,解决方法有两个,一个是将 scroll 事件绑定到 body 上,另一个就是将 html,body
上的 overflow:auto/scroll
改成其他的属性值,比如 initial
、visible
、inherit
等,或者干脆去掉也行。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。