如何判断有没有出现滚动条

API

API 说明
clientWidth                                                                           内联元素以及没有 CSS 样式的元素的 clientWidth 属性值为 0。
Element.clientWidth 属性表示元素的内部宽度,以像素计。
该属性包括内边距 padding,但不包括边框 border、外边距 margin 和垂直滚动条(如果有的话)。
offsetWidth HTMLElement.offsetWidth 是一个只读属性,返回一个元素的布局宽度。
一个典型的(译者注:各浏览器的offsetWidth可能有所不同)offsetWidth是测量包含元素的边框(border)、水平线上的内边距(padding)、竖直方向滚动条(scrollbar)(如果存在的话)、以及CSS设置的宽度(width)的值。
scrollWidth Element.scrollWidth 这个只读属性是元素内容宽度的一种度量,包括由于overflow溢出而在屏幕上不可见的内容。
scrollWidth值等于元素在不使用水平滚动条的情况下适合视口中的所有内容所需的最小宽度。
宽度的测量方式与clientWidth相同:它包含元素的内边距,但不包括边框,外边距或垂直滚动条(如果存在)。 它还可以包括伪元素的宽度,例如::before::after。 如果元素的内容可以适合而不需要水平滚动条,则其scrollWidth等于clientWidth
clientHeight 这个属性是只读属性,对于没有定义CSS或者内联布局盒子的元素为0,否则,它是元素内部的高度(单位像素),包含内边距,但不包括水平滚动条、边框和外边距。
offsetHeight HTMLElement.offsetHeight 是一个只读属性,它返回该元素的像素高度,高度包含该元素的垂直内边距和边框,且是一个整数。
通常,元素的offsetHeight是一种元素CSS高度的衡量标准,包括元素的边框、内边距和元素的水平滚动条(如果存在且渲染的话),不包含:before或:after等伪类元素的高度。
scrollHeight Element.scrollHeight 这个只读属性是一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容。
scrollHeight的值等于该元素在不使用滚动条的情况下为了适应视口中所用内容所需的最小高度。 没有垂直滚动条的情况下,scrollHeight值与元素视图填充所有内容所需要的最小值clientHeight相同。包括元素的padding,但不包括元素的border和margin。scrollHeight也包括 ::before::after这样的伪元素。

此属性会将获取的值四舍五入取整数。 如果你需要小数结果, 请使用 element.getBoundingClientRect().

image.png

水平方向滚动条

我们要判断一个div上有没有出现水平方向滚动条,只需判断scrollWidth是否大于clientWidth即可。

当border为0时,使用offsetHeight - clientHeight可以得到水平滚动条的宽度(如果有的话)。

垂直方向滚动条

我们要判断一个div上有没有出现垂直方向滚动条,只需判断scrollHeight是否大于clientHeight即可。

当border为0时,使用offsetWidth - clientWidth可以得到垂直滚动条的宽度(如果有的话)。

但是在IE浏览器上,某些特殊情况下,虽然scrollHeight > clientHeight(或scrollWidth > clientWidth),也不一定出现滚动条。

API 父元素 子元素
Element.clientHeight 257 258
Element.offsetHeight 257 258
Element.scrollHeight 258 258
Element.getBoundingClientRect().height 257 257.92999267578125
Element.clientWidth 840 840
Element.offsetWidth 840 840

我们发现,在这种特殊情况下,虽然父元素的 scrollHeight(258)> clientHeight(257),并且实际内容的高度是257.92999267578125,的确父元素应该出现滚动条,但实际在IE浏览器上没有显示滚动条,这一点我们从数据 父元素的 offsetWidth(840)- clientWidth(840)= 0 也可得出。

通常情况下,我们可以使用scrollWidth > clientWidth 判断是否出现水平滚动条, scrollHeight > clientHeight 判断是否出现垂直滚动条。

在需要更精确(非移动端且非overflow: hidden 或 overlay)或要拿到滚动条宽度的情况下,我们可以使用 offsetHeight - clientHeight(水平滚动条) 或 offsetWidth - clientWidth(垂直滚动条),这时,我们不要忘了减去元素的border

更复杂情况下的判断

有时候情况比较复杂,比如滚动区域宽度是不固定的,我们需要根据是否出现滚动条来设置滚动区域宽度(比如,出现滚动条时给左右加上点击按钮,来切换显示区域)。这时我们就需要来计算内部各元素宽度之和来判断是否出现滚动条。
这里写了个例子,我们来看一下,运行环境为Windows电脑,Chrome浏览器

API 父元素 子元素1 子元素2
Element.getBoundingClientRect().width 341.375 98.40625 240.96875
getComputedStyle(Element).width 341.375px 98.4063px 240.969px
Element.clientWidth 341 98 241
Element.offsetWidth 341 98 241
Element.scrollWidth 341 98 241
getComputedStyle(Element).marginRight 0px 2px 0px

这里子元素1上有一个marginRight的值:2px

clientWidthoffsetWidthscrollWidth属性会进行四舍五入并返回整数。当子元素有多个时相加,误差会越来越大。

getComputedStyle

我们来看一下getComputedStyle的值

98.4063(子元素1宽度)+ 2(子元素1 margin-right)+ 240.969(子元素2宽度)= 341.3753

我们发现内容宽度341.3753 > 父元素宽度341.375
getComputedStyle存在一个小的精度误差。

getBoundingClientRect

我们再来看一下getBoundingClientRect获取到的宽度

98.40625(子元素1宽度)+ 2(子元素1 margin-right)+ 240.96875(子元素2宽度)= 341.375

我们发现内容宽度341.375 与 父元素宽度341.375 相等。

那我们这里就选用getBoundingClientRect吧,但是......

浏览器放大或缩小

我们把浏览器放大至150%再来看一下

API 父元素 子元素1 子元素2
Element.getBoundingClientRect().width 341.35418701171875 98.39583587646484 240.95834350585938
getComputedStyle(Element).width 341.354px 98.3958px 240.958px
Element.clientWidth 341 99 241
Element.offsetWidth 341 99 241
Element.scrollWidth 341 99 241
getComputedStyle(Element).marginRight 0px 2px 0px

我们使用getBoundingClientRect的值计算一下

98.39583587646484(子元素1宽度)+ 2(子元素1 margin-right)+ 240.95834350585938(子元素2宽度)= 341.3541793823242

我们发现得到的值为341.3541793823242,与获取到的父元素的值341.35418701171875仍存在一个微小的偏差(这个偏差可能是大,也可能是小)。

因此,我们引入一个微小的忽略值0.1,认为当 父元素的宽度 + 0.1 大于 内容宽度计算结果 时,没有滚动条。

341.35418701171875 + 0.1 > 341.3541793823242 

参考文档:
MDN Element.clientWidth
MDN HTMLElement.offsetWidth
MDN Element.scrollWidth
MDN Element.clientHeight
MDN HTMLElement.offsetHeight
MDN Element.scrollHeight

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