js中获取dom尺寸【简单易懂】👌
前言
直接要答案的,看目录中的最佳实践。
根据实际应用场景不同,选择的方法至关重要。
前置知识
前置知识可帮助你快速了解到一个盒子的组成部分。
首先我们要知道一个盒子的组成部分分为4个,
- 内容区域
Content Box
- 内边距
Padding
- 边框
Border
<滚动条属于边框部分> - 外边距
margin
外边距作为盒子外部的区域,定义的是元素与其他元素之间的空白区域,常用做布局中的间距调整,所以大多数情况,我们要获取的盒子大小,不包括外边距。
现在可以了解一下box-sizing
属性了。👀
定义:
CSS中的box-sizing属性定义了user agent应该如何计算一个元素的总宽度和总高度
通俗的理解 box-sizing
的值,决定了代码中width或height的值指向盒子的那些部分。
属性值:
box-sizing
:content-box
;<默认值>
content-box
默认值,标准盒子模型。width
与height
只包括内容的宽和高,不包括边框(border),内边距(padding),外边距(margin)。注意:内边距、边框和外边距都在这个盒子的外部。比如说,.box {width: 350px; border: 10px solid black;}
在浏览器中的渲染的实际宽度将是 370px。尺寸计算公式:
width
= 内容的宽度
height
= 内容的高度宽度和高度的计算值都不包含内容的边框(border)和内边距(padding)
我将其通俗理解为 在值为content-box
的时候,你所定义的width
和height
指的是内容区域Content Box
的宽高,并不包括内边距Padding
和边框Border
下面看图理解
代码中三个盒子都指定了宽高为100px,但是给第二个盒子加了10px内边距,他渲染出来就比100px大,给第三个盒子加了20px的边框,他渲染出来就比100px大。也就是说你所指定的宽高只是内容区域的宽高,并不包括内边距和边框,所以在这种模式下,浏览器最终渲染出的尺寸和你所指定的尺寸并不一定相等。
width
和height
属性包括内容,内边距和边框,但不包括外边距。这是当文档处于 Quirks 模式 时 Internet Explorer 使用的盒模型。注意,填充和边框将在盒子内 , 例如,.box {width: 350px; border: 10px solid black;}
导致在浏览器中呈现的宽度为 350px 的盒子。内容框不能为负,并且被分配到 0,使得不可能使用 border-box 使元素消失。
也就是说在值为border-box
的时候,你所定义的width
和height
就已经包括了内边距和边框
继续看图理解
这次在指定了box-sizing: border-box后,再给盒子添加内边距或边框,都不会改变你所定义的盒子大小了。
但是!但是有个例外情况 看下图
当你的边框或者内边距,超过你指定的宽高时,盒子就会被撑大了,上图可以看到,当边框为51px时,盒子就变大了,因为左边框右边框 加起来102px,已经超过盒子的原本宽度100px,但是这种情况基本不会遇到吧。
所以在值为border-box
并且边框和内边距不大于你所指定的尺寸时,浏览器最终渲染出的尺寸和你所指定的尺寸就相等。
非标准,不推荐使用
注意:这个值在大多数浏览器中不支持,不建议在生产环境中使用。
正文开始✌
1. dom.style.width ❌
此方法只能获取行内样式,并且获取的只是行内样式中你所书写的宽度,并不一定是渲染出来的真正宽度。看图
第一个盒子没写行内样式,所以dom.style.width获取到是空字符串。
第二个盒子行内样式写的auto,获取到就是auto字符串,并不是真正大小。
第三个盒子行内样式写的100px,但是在box-sizing值为content-box的情况下,20px的边框已经把盒子撑的宽度超过100px,但是获取的还是100px。
你行内样式写的是什么,获取的就是什么,因为他读的就是DOM树。所以在日常开发中,dom.style.····常被用做在js中赋予dom新样式,因为行内样式权重大嘛。
2. getComputedStyle(b1).width ❌
这个方法获取的是CSSOM树,就是说他获取的是在代码层面最终计算出来的元素尺寸。但是!但是根据前置知识,当box-sizing的值为content-box也就是默认值的时候,你所指定的宽度width
只是内容区域的宽度,并不是最终渲染出来的宽度。这个情况下用getComputedStyle(b1).width获取的宽度就是内容区域宽度,并不是最终渲染出来的宽度。
1. 第一个盒子,就是正常情况,获取的100px。
2. 第二个盒子,行内样式的auto覆盖了,类样式的100px,最终也是获取到当前盒子的最终宽度。
3. 第三个盒子,获取到的100px只是代码层面的宽度,并不是浏览器渲染出来的宽度,因为边框已经影响了渲染结果。
3.最佳实践方法看这里✔
3.1获取 内容区域 + 内边距区域 clientWidth
const box = document.querySelector(".box");
console.log("box的内容区域+内边距区域", box.clientWidth);
3.2 获取可滚动区域 scrollWidth
const box = document.querySelector(".box");
console.log("box的可滚动区域", box.scrollWidth);
那么可滚动区域什么意思呢?
包括由于 overflow 溢出而在屏幕上不可见的内容。
获取的可滚动区域宽度775px,远远超出了代码指定的width:300px。
那它获取的究竟是哪里的宽度?看下图
scrollWidth获取可滚动区域包含内边距,不包含边框。
3.3 获取内容区域 + 内边距区域 + 边框区域<包含滚动条区域>offsetWidth
const box = document.querySelector(".box");
console.log("box的内容区域+内边距区域+边框区域<包含滚动条区域>", box.offsetWidth);
这个方法看似完美,可以获取到我们想要的可视区域<我眼睛看到这个盒子的区域>尺寸, 其实他也会被CSS 的 transform
属性影响。
3.4 获取可视区域 getBoundingClientRect()
const box = document.querySelector(".box");
console.log("box的可视区域", box.getBoundingClientRect().width);
这个方法就是获取可视区域尺寸,最可靠的方法,这个方法就是获取的浏览器实际渲染到页面上的尺寸。
目录3.3的 offsetWidth
和 getBoundingClientRect()
看着很是相似,下面是一些区别。
当元素应用了 CSS 的
transform
属性(如旋转、缩放等)时,getBoundingClientRect().width
会反映出这些变换后的实际渲染宽度,而offsetWidth
则不会考虑这些变换,它返回的是未经过变换的原始宽度。
转载自:https://juejin.cn/post/7375072185209520140