overflow属性引发的浏览器滚动条血案

案发现场

今天给后台的表格组件替换为一个前同事写的表格组件,替换完发现除了滚动条不能用鼠标滚动以外,其他都没什么大问题。我是一个跟任何东西都可以较劲的人,我不信一个小小的滚动条还能奈我何?于是就发生了这个血案。从看源码,到问前同事,足足浪费了我一个下午来找问题,深深地感到自己的能力是如此的不足。

案发详情

滚动条归属的问题。

我们都知道,如何页面超过了浏览器窗口的大小,浏览器会自动生成一个滚动条。这个滚动条是属于谁的?是属于html元素还是body元素的?

都不是!!

当一个子元素超过了其父元素的限定高度并且在父元素设置了overflow:auto或者overflow:scroll父元素容器就会产生一个滚动条,这个滚动条毫无疑问是归属于父元素的。直接看demo01,以下是demo01的主要代码:

<div class="parent">
    parent
    <div class="child">
        child
    </div>
</div>
body{
    margin:0;
}
.parent{
    height:400px;
    border:1px solid #ddd;
    overflow:auto;
}

.child{
    height:800px;
    background-color:#eee;
}

可以看到,child撑开了parent的高度,于是parent生成了滚动条,滚动条属于parent,这个是没有争议的。

如何判断滚动条的归属呢?

一种直观的方法:可以通过控制台的Element面板,把鼠标hover在parent元素上,可以看到滚动条是在元素内部的。(在Mac下,滚动条的表现形式不太一样,只有滚动的时候才会出现滚动条,没有滚动时自动隐藏)

另一种方法是可以通过对元素添加scroll监听事件来判断。

如果是body下的直接子元素的高度超过了body的限定高度,并且给body增加overflow :auto,这时生成的滚动条是属于谁的?看一下例子demo02,以下是主要代码:

<div class="child">
    Child
</div>
html, body{
    height:100%;
}
body{
    margin:0;
    overflow:auto;
}
.child{
    height:1000px;
    background-color:#eee;
}

咦,好像滚动条并不属于body元素??确实不属于body,也不属于html。Mac下按照上面第一种方法观察,滚动条好像是属于html元素的,但其实不然,可以通过给元素添加scroll事件的监听就可以发现,滚动的时候并不会触发html元素或者body元素的scroll事件。

//监听window窗口的滚动事件
window.addEventListener('scroll', (e) => {
    console.log('window');
})
//监听document对象的滚动事件
document.addEventListener('scroll', (e) => {
    console.log('document');
})
//监听html元素的滚动事件
document.documentElement.addEventListener('scroll', (e) => {
    console.log('html');
})
//监听body元素的滚动事件
document.body.addEventListener('scroll', (e) => {
    console.log('body');
})

上面的四个监听器,滚动的时候只有前两个才会被触发,所以证明滚动条是属于document对象的。

为什么window也能监听到scroll事件呢?这是因为事件冒泡

当html元素也添加overflow:auto时,滚动条会是谁的呢?看例子demo03

这时,滚动条貌似是属于body的?是的没错,就是属于body的,用监听器来监听一下滚动事件,只会触发document.body的监听器,而不会触发windowdocument的。

为什么会这样?应该不仅只有我一个人才发现滚动条这个坑的吧?TAT

先来回顾一下overflow有哪些值:

/* 默认值。内容不会被修剪,会呈现在元素框之外*/
overflow: visible;

/* 内容会被修剪,并且其余内容不可见 */
overflow: hidden;

/* 内容会被修剪,浏览器会显示滚动条以便查看其余内容 */
overflow: scroll;

/* 由浏览器定夺,如果内容被修剪,就会显示滚动条 */
overflow: auto;

/* 规定从父元素继承overflow属性的值 */
overflow: inherit;

于是得出结论(也可以说个人猜测,因为不一定正确):

htmlbody仅有一个元素会产生滚动条时,这个滚动条会默认归属于document

htmlbody元素的overflow属性都是默认值auto时,因为body高度可能超过html的高度,这时就会产生一个滚动条,这个滚动条属于document的,所以如果body再产生一个滚动条,就只能是属于body自己的了。

鼠标滚轮事件

页面出现滚动条时,我们可以用鼠标滚轮来对页面进行纵向滚动,那是否可以组织这个滚动行为呢?

肯定是可以的。e.preventDefault()就是阻止事件的默认行为,在mousewheel事件监听里加上这句,就能阻止鼠标滚轮触发滚动事件了。

戳栗子demo04

因为这个,让我在组件源码里折腾了好一会,当然不是不知道e.preventDefault(),是忽略了它的作用。


因为工作忙,这篇文章前后写了好久,当时的一些思路灵感都已经消逝了,写不下去了,先到这为止吧,之后有想起什么遗漏的再补上。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,009评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,808评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,891评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,283评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,285评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,409评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,809评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,487评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,680评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,499评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,548评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,268评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,815评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,872评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,102评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,683评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,253评论 2 341