0


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

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

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


一. 前期准备

  1. 在学习这几个概念之前,我强烈建议你用你喜欢的框架或者工具去简单写一个 <div> 元素来更深刻的体会我接下来讲解的内容。不用特别复杂,十分简单的,带有宽度高度的 div 即可。image.png 在页面上的效果如下。image.png
  2. 接下来你需要进入到开发者页面,选中刚刚我们创造的这个 div 元素。image.png
  3. 然后你需要从右边的选项卡中找到 Properties(dom 属性) 这一项中筛选出带有 width 的几个属性。width.gif 接下来你将会频繁的看到这三个属性的变化。

二. clientWidth

  1. 三个属性中我们先对 clientWidth 初步讲解一下。
  2. 我相信大家初次去 MDN 查阅这个 Css 属性的时候,一定看到过下面这张图。image.png
  3. 初次看到这张图,感觉它什么都讲了,但是又好像不知道它到底想表达什么。如果你也有这样的疑惑,本文将带你一步步去体会它到底想表达什么。
  4. 首先切忌死记硬背属性名,我们需要十分明确的知道这个属性名为什么叫 clientWidth 而不是叫 小猪佩奇Width。下面是这个单词的翻译,我认为 client 这个单词在这里语境中最佳的翻译应该为—“客户端,用户端”image.png
  5. ok,我知道你可能还是有疑惑,别着急,我们一步一步来。经过上面 width 属性搜索结果可知,聪明的你可能已经发现 clientWidth 的值不就是我们给这个 box 设置的 width 的属性值 100 吗?image.png
  6. 是的,对了,但是不完全对。这里更好的说法应该是:“按照我们现在的布局和样式,clientWidthwidth是相等的。”对,只能称作它们的是相等的,而不能说这两个属性是全等的。
  7. 那这个 clientWidth 到底该怎么去理解呢?“客户端的宽度用户端的宽度?”总感觉哪里怪怪的。🤔
  8. 在这里我先抛出一个我个人认为比较贴切的说法:“clientWidth 指的是一个 dom 元素中,当前状态下可以被用户即时看到的宽度(理解为可视区域的宽度或许也可以)。
  9. ”什么意思?假设你现在面前放着一个空的正方体的快递盒子📦。里面填充了一个大小恰好一模一样的黑色正方体铁块。那么你目前看到的这个铁块的宽度就称作快递盒子(box)的 clientWidth
  10. 现在我们把铁块取出来,得到了一个空的盒子对吧?现在我在盒子周围贴上了一圈10厘米宽的白色泡沫板。然后又找来了一个小一号的,但是又恰好可以一起塞进箱子里的铁块。体现到我们的例子上就是 box 加上了 10px 的 border 属性。image.pngimage.png 然后我们再去 Properties 选项卡查看这三个属性。image.png
  11. 我们发现 clientWidth 的宽度减少了 20px。(我们不是只设置了 10px 吗?怎么一下子减少了 20px 呢?我希望你不要忘了,border 如果没指定具体方向的话,它会在上下左右都设定一份…就像你在快递盒子四个边都塞了一份泡沫板)
  12. 此时你能看到的铁块的宽度就是 clientWidth,我们好像可以得出一个结论,clientWidth = width- 左border - 右border。不对,不能这么早下结论,我们好像遗忘了一个一个重要属性 padding。我们目前还不知道 padding 会不会影响 clientWidht 的值。ok,那我们就验证一下,现在我们给这个盒子添加一个 10px 的 padding 看一下会不会发生什么变化。image.png 可以看出,我们加的 padding 好像确实没有影响到 clientWidth 的宽度。image.png 我们刚刚得出的 clientWidth = width- 左border - 右border 看来还是站得住脚的。
  13. 其实在这里我更想表达的是,我们在理解 padding 这个属性的时候,我们其实可以把它理解为内容区的一部分。因为 padding 属性其实也是受到了 bg-color(background-color) 的影响,而 border 属性是没有受到 bg 影响而变为黑色的。这也是为什么 padding 没有 padding-color 这一属性的原因,因为它本身是被当成了内容区的一一部分,它的颜色是随着内容区(也就是 bg-color) 而改变的原因。
  14. 这时候我们再去看这张图,这里 padding 为什么有颜色?这其实是 MDN 为了更好的去表现出 padding 属性而“特意”添加上了不同颜色的。 image.png 所以, clientWidth 这一属性更像是描述用户可以直接看到的内容区域。
  15. tips: 这里需要特别注意!!我们现在的结论是站在 box-sizing 属性为 border-box 的前提下的,后面我会讲解到 box-sizingcontent-boxclientWidth 的不同。

三. offsetWidth

  1. 关于 offsetWidth,其实 MDN 有这样一句话能够很完美的表现出它想表达的意思。image.png
  2. 它的概念其实非常非常简单,就是在 box-sizing:border 的时候 offsetWidth 其实就等于 dom 元素的 width。不知道你是否遗忘了 box-sizing:content 这个标准盒子模型的概念。让我们切换一下 box-sizing 的属性,变为 content 来看看这个属性值有什么变化。image.pngimage.png 可以很清楚的看到,在 box-sizing:conetent 的时候 offsetWidth= width + 左border + 右border + 左padding + 右padding

这是因为在

content-box

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

border-box

下设置的

border

padding

都是由盒子向内部收缩来给 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
<template>
  <div class="box">希望大家可以从我博客中学到一些新的知识</div>
</template>

<style scoped>
.box {
  width: 100px;
  height: 100px;
  font-size: 20px;
  white-space: nowrap;
  color: red;
  background: black;

  border: 10px solid blue; /* 10cm 的泡沫板 */
  padding: 10px;
}
</style>
![image.png](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e4ae5bf5960248fba5bae33d8c9bd11e~tplv-k3u1fbpfcp-watermark.image?)
  1. 很清楚的看到,由于我们的字体宽度过大,导致盒子塞不下,但是我们又没有设置溢出场景的处理方法,就导致了现在的样子。image.png
  2. 我想你已经迫不及待的去 Properties 去查看这几个属性了,但是你有可能一脸疑惑的回来。image.png 什么情况,这 scrollWidth 也没变啊!我怀疑你在骗我。😠
  3. 其实从 scroll 这个词我们猜或许也能猜到什么。image.png 既然和“滚动”有关,那么现在页面发生滚动了吗?没有,怎么才可以滚动呢?没错 overflow-auto(其它值也一样,只不过 auto 方便一点)。
  4. 设置了 overflow 的处理后,我们现在页面应该是下面这个样子。image.png 我们再去查看这三个属性,你会发现 scrollWidth 已经变了。image.png
  5. 那 390 这个数值是怎么来的呢?这个其实数值要根据你实际项目造成溢出的原因来分析的。但是 scrollWidth 这个属性实际上代表的是“dom元素内容区的真实宽度”。什么意思呢?让我们先把 overflow-auto 属性删除,恢复成它原来溢出的样子。image.png
  6. 然后我们需要通过一些“特殊的手法”去测量一下这个值是体现在哪里。overflow.gif 390 实际上就是文字区域+ padding 区域的宽度。说的直白一点,其实就是内容区(content)。(我再强调一下,你可以把 padding 理解为特殊的内容区
  7. 没错,到这里我想你大概已经明白了,实际上 scrollWidth 代表的就是内容区的真实宽度。在这里我们就需要把 clientWidth 拎出来讲一下了。同样是表达内容区宽度的。

1.在内容区没有发生溢出的情况下,scrollWidth = clientWidth 因为它们都是代表内容区的宽度。
2.在内容区发生了溢出,并且设置了 overflow-scroll 之类的属性的情况下,

clientWidth

代表dom 当前状态下,实际上展示在可视区域的 内容区(content) 的宽度,而 scrollWidth 则代表了真实的内容区的宽度,包括了那些没有展现在用户面前的,需要滚动才可以看到的内容的宽度。这时候
scrollWidth= clientWidth + 溢出的内容区的宽度

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

结语

这三个属性所对应的

offsetHeight

clientHeigh

scrollHeight

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

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

标签: html 前端 css

本文转载自: https://blog.csdn.net/fang_my/article/details/128994099
版权归原作者 韩振方 所有, 如有侵权,请联系我们删除。

“你必须知道的 clientWidth, offsetWidth, scrollWidth.”的评论:

还没有评论