你必须知道的 clientWidth, offsetWidth, scrollWidth.
前言: 在公司移动端项目中,我需要十分频繁的和 DOM 元素的各种 width、height 打交道。但是这里有这么多关于 width 的属性,它们之间的区别到底体现在哪里?这是我刚刚接触移动端项目十分头疼的一个问题。经过几天的查阅,终于搞明白了这几个的不同之处,特来分享。
tips: 本文意指让你自己通过联想记牢这几个属性的区别,而不是单纯地表达它们概念上的不同,故篇幅会较长,还希望读者耐下心细细品读☕️。
一. 前期准备
-
在学习这几个概念之前,我强烈建议你用你喜欢的框架或者工具去简单写一个
<div>
元素来更深刻的体会我接下来讲解的内容。不用特别复杂,十分简单的,带有宽度高度的div
即可。在页面上的效果如下。
-
接下来你需要进入到开发者页面,选中刚刚我们创造的这个
div
元素。 -
然后你需要从右边的选项卡中找到
Properties(dom 属性)
这一项中筛选出带有 width 的几个属性。接下来你将会频繁的看到这三个属性的变化。
二. clientWidth
三. offsetWidth
-
关于
offsetWidth
,其实MDN
有这样一句话能够很完美的表现出它想表达的意思。 -
它的概念其实非常非常简单,就是在
box-sizing:border
的时候 offsetWidth 其实就等于 dom 元素的 width。不知道你是否遗忘了box-sizing:content
这个标准盒子模型的概念。让我们切换一下box-sizing
的属性,变为content
来看看这个属性值有什么变化。可以很清楚的看到,在
box-sizing:conetent
的时候 offsetWidth= width + 左border + 右border + 左padding + 右padding。
这是因为在
content-box
的情况下,我们设置的 dom 元素的宽度其实仅仅只是内容区的宽度。我们设置的 border 和 padding 都是由内容区向外扩张。
在
border-box
下设置的border
和padding
都是由盒子向内部收缩来给 border 或者 padding “腾地方”。
-
而
offsetWidth
这个属性是为了表达了盒子的真实物理宽度。所以它的计算方式会根据box-sizing
的不同而不同。 -
在这里你可能会好奇,为什么
clientWidth
也跟着变了?其实根据我们上面讲的:“padding
其实是算作特殊的内容区”来分析,很容易就可以想到clientWidth= 100px+ 10px + 10px
, 所以就等于了 120px。
四. scrollWidth
-
为什么在上面我压根没提这个属性呢?因为这个属性的触发条件很特殊,它只有在特殊的场景下才能体现出和
clientWidth
的区别。(tips:它确实是需要对标clientWidth
的,先不要疑惑,接着往下看你就明白为什么对标的是clientWidth
而不是offsetwidht
了。) -
那这个“特殊场景”指的是什么呢?其实你应该非常熟悉----
overflow
。 -
ok,那我们怎么创建这个特殊场景呢?其实非常非常简单,你在这个 100px 宽度的盒子里多打几个字就可以。 我们简单设置一下字体的颜色和大小。注意:这里我们已经把
box-sizing
切换成了border-box
,这里为了表现溢出,我们需要设置一个特殊的属性white-space:nowrap
-
很清楚的看到,由于我们的字体宽度过大,导致盒子塞不下,但是我们又没有设置溢出场景的处理方法,就导致了现在的样子。
-
我想你已经迫不及待的去
Properties
去查看这几个属性了,但是你有可能一脸疑惑的回来。什么情况,这
scrollWidth
也没变啊!我怀疑你在骗我。😠 -
其实从
scroll
这个词我们猜或许也能猜到什么。既然和“滚动”有关,那么现在页面发生滚动了吗?没有,怎么才可以滚动呢?没错
overflow-auto
(其它值也一样,只不过auto
方便一点)。 -
设置了
overflow
的处理后,我们现在页面应该是下面这个样子。我们再去查看这三个属性,你会发现
scrollWidth
已经变了。 -
那 390 这个数值是怎么来的呢?这个其实数值要根据你实际项目造成溢出的原因来分析的。但是
scrollWidth
这个属性实际上代表的是“dom元素内容区的真实宽度”。什么意思呢?让我们先把overflow-auto
属性删除,恢复成它原来溢出的样子。 -
然后我们需要通过一些“特殊的手法”去测量一下这个值是体现在哪里。
390 实际上就是文字区域+
padding
区域的宽度。说的直白一点,其实就是内容区(content)。(我再强调一下,你可以把padding
理解为特殊的内容区) -
没错,到这里我想你大概已经明白了,实际上
scrollWidth
代表的就是内容区的真实宽度。在这里我们就需要把clientWidth
拎出来讲一下了。同样是表达内容区宽度的。
1.在内容区没有发生溢出的情况下,scrollWidth = clientWidth 因为它们都是代表内容区的宽度。 2.在内容区发生了溢出,并且设置了 overflow-scroll 之类的属性的情况下,
clientWidth
代表dom 当前状态下,实际上展示在可视区域的 内容区(content) 的宽度,而 scrollWidth 则代表了真实的内容区的宽度,包括了那些没有展现在用户面前的,需要滚动才可以看到的内容的宽度。这时候 scrollWidth= clientWidth + 溢出的内容区的宽度。
- 所以
clientWidth
更确切的中文翻译应该是---客户端可视区域内,内容区的宽度。
结语
这三个属性所对应的 offsetHeight
、clientHeigh
和 scrollHeight
都是同样的道理,在这里就不重复赘述了,希望读者可以自己举一反三自行推导这三个属性代表什么意思。
从学习这几个属性的过程中才真正体会到:“看一千遍文档,不如自己动手实践一遍”的道理。还希望大家也可以跟着自己敲一敲,真的不难。与君共勉才是我写这篇文章的初衷~
转载自:https://juejin.cn/post/7196128985612189752