likes
comments
collection
share

你必须知道的 clientWidth, offsetWidth, scrollWidth.

作者站长头像
站长
· 阅读数 16

前言: 在公司移动端项目中,我需要十分频繁的和 DOM 元素的各种 widthheight 打交道。但是这里有这么多关于 width 的属性,它们之间的区别到底体现在哪里?这是我刚刚接触移动端项目十分头疼的一个问题。经过几天的查阅,终于搞明白了这几个的不同之处,特来分享。

tips: 本文意指让你自己通过联想记牢这几个属性的区别,而不是单纯地表达它们概念上的不同,故篇幅会较长,还希望读者耐下心细细品读☕️。


一. 前期准备

  1. 在学习这几个概念之前,我强烈建议你用你喜欢的框架或者工具去简单写一个 <div> 元素来更深刻的体会我接下来讲解的内容。不用特别复杂,十分简单的,带有宽度高度的 div 即可。 你必须知道的 clientWidth, offsetWidth, scrollWidth. 在页面上的效果如下。 你必须知道的 clientWidth, offsetWidth, scrollWidth.

  2. 接下来你需要进入到开发者页面,选中刚刚我们创造的这个 div 元素。 你必须知道的 clientWidth, offsetWidth, scrollWidth.

  3. 然后你需要从右边的选项卡中找到 Properties(dom 属性) 这一项中筛选出带有 width 的几个属性。 你必须知道的 clientWidth, offsetWidth, scrollWidth. 接下来你将会频繁的看到这三个属性的变化。

二. clientWidth

三. offsetWidth

  1. 关于 offsetWidth,其实 MDN 有这样一句话能够很完美的表现出它想表达的意思。 你必须知道的 clientWidth, offsetWidth, scrollWidth.

  2. 它的概念其实非常非常简单,就是在 box-sizing:border 的时候 offsetWidth 其实就等于 dom 元素的 width。不知道你是否遗忘了 box-sizing:content 这个标准盒子模型的概念。让我们切换一下 box-sizing 的属性,变为 content 来看看这个属性值有什么变化。 你必须知道的 clientWidth, offsetWidth, scrollWidth. 你必须知道的 clientWidth, offsetWidth, scrollWidth. 可以很清楚的看到,在 box-sizing:conetent 的时候 offsetWidth= width + 左border + 右border + 左padding + 右padding

这是因为在 content-box 的情况下,我们设置的 dom 元素的宽度其实仅仅只是内容区的宽度。我们设置的 border 和 padding 都是由内容区向外扩张。

border-box 下设置的 borderpadding 都是由盒子向内部收缩来给 border 或者 padding “腾地方”。

  1. offsetWidth 这个属性是为了表达了盒子的真实物理宽度。所以它的计算方式会根据 box-sizing 的不同而不同。

  2. 在这里你可能会好奇,为什么 clientWidth 也跟着变了?其实根据我们上面讲的:“padding 其实是算作特殊的内容区”来分析,很容易就可以想到 clientWidth= 100px+ 10px + 10px, 所以就等于了 120px。

四. scrollWidth

  1. 为什么在上面我压根没提这个属性呢?因为这个属性的触发条件很特殊,它只有在特殊的场景下才能体现出和 clientWidth 的区别。(tips:它确实是需要对标 clientWidth 的,先不要疑惑,接着往下看你就明白为什么对标的是 clientWidth 而不是 offsetwidht 了。)

  2. 那这个“特殊场景”指的是什么呢?其实你应该非常熟悉----overflow

  3. ok,那我们怎么创建这个特殊场景呢?其实非常非常简单,你在这个 100px 宽度的盒子里多打几个字就可以。 我们简单设置一下字体的颜色和大小。注意:这里我们已经把 box-sizing 切换成了 border-box,这里为了表现溢出,我们需要设置一个特殊的属性 white-space:nowrap

  1. 很清楚的看到,由于我们的字体宽度过大,导致盒子塞不下,但是我们又没有设置溢出场景的处理方法,就导致了现在的样子。 你必须知道的 clientWidth, offsetWidth, scrollWidth.

  2. 我想你已经迫不及待的去 Properties 去查看这几个属性了,但是你有可能一脸疑惑的回来。 你必须知道的 clientWidth, offsetWidth, scrollWidth. 什么情况,这 scrollWidth 也没变啊!我怀疑你在骗我。😠

  3. 其实从 scroll 这个词我们猜或许也能猜到什么。 你必须知道的 clientWidth, offsetWidth, scrollWidth. 既然和“滚动”有关,那么现在页面发生滚动了吗?没有,怎么才可以滚动呢?没错 overflow-auto(其它值也一样,只不过 auto 方便一点)。

  4. 设置了 overflow 的处理后,我们现在页面应该是下面这个样子。 你必须知道的 clientWidth, offsetWidth, scrollWidth. 我们再去查看这三个属性,你会发现 scrollWidth 已经变了。 你必须知道的 clientWidth, offsetWidth, scrollWidth.

  5. 那 390 这个数值是怎么来的呢?这个其实数值要根据你实际项目造成溢出的原因来分析的。但是 scrollWidth 这个属性实际上代表的是“dom元素内容区的真实宽度”。什么意思呢?让我们先把 overflow-auto 属性删除,恢复成它原来溢出的样子。 你必须知道的 clientWidth, offsetWidth, scrollWidth.

  6. 然后我们需要通过一些“特殊的手法”去测量一下这个值是体现在哪里。 你必须知道的 clientWidth, offsetWidth, scrollWidth. 390 实际上就是文字区域+ padding 区域的宽度。说的直白一点,其实就是内容区(content)。(我再强调一下,你可以把 padding 理解为特殊的内容区

  7. 没错,到这里我想你大概已经明白了,实际上 scrollWidth 代表的就是内容区的真实宽度。在这里我们就需要把 clientWidth 拎出来讲一下了。同样是表达内容区宽度的。

1.在内容区没有发生溢出的情况下,scrollWidth = clientWidth 因为它们都是代表内容区的宽度。 2.在内容区发生了溢出,并且设置了 overflow-scroll 之类的属性的情况下,clientWidth 代表dom 当前状态下,实际上展示在可视区域的 内容区(content) 的宽度,而 scrollWidth 则代表了真实的内容区的宽度,包括了那些没有展现在用户面前的,需要滚动才可以看到的内容的宽度。这时候 scrollWidth= clientWidth + 溢出的内容区的宽度

  1. 所以 clientWidth 更确切的中文翻译应该是---客户端可视区域内,内容区的宽度。

结语

这三个属性所对应的 offsetHeightclientHeighscrollHeight 都是同样的道理,在这里就不重复赘述了,希望读者可以自己举一反三自行推导这三个属性代表什么意思。

从学习这几个属性的过程中才真正体会到:“看一千遍文档,不如自己动手实践一遍”的道理。还希望大家也可以跟着自己敲一敲,真的不难。与君共勉才是我写这篇文章的初衷~