box-sizingoffsetWidthclientWidthclientLeft

DOM元素的尺寸

box-sizing对属性的影响

box-sizing的属性值会直接影响盒模型的尺寸计算。一般常用的box-sizing值有几个:

content-box: (默认值)标准盒模型。width = 内容的宽度,height = 内容的高度。宽度和高度都不包含内容的边框(border)和内边距(padding)
border-box:width 和 height 属性包括内容,填充和边框,但不包括边距。
padding-box: 只有火狐支持了,不展开研究

以下面的代码为例。

1
2
<div id="boderBox" style="width: 200px;height: 100px;box-sizing: border-box;border: 5px solid #123456; margin: 20px 10px; padding: 7px;"></div>
<div id="contentBox" style="width: 200px;height: 100px;box-sizing: content-box;border: 5px solid #654321; margin: 20px 10px; padding: 7px;"></div>
1
2
3
4
$boderBox = document.querySelector('#boderBox');
$contentBox = document.querySelector('#contentBox');
console.info('offsetWidth', $boderBox.offsetWidth); // 200
console.info('offsetWidth', $contentBox.offsetWidth); // 224

可见border-boxcontent-box获取到的offsetWidth值是不同的。content-box
计算方法:

1
offsetWidth = 200(内容宽度) + 5 * 2(左右border宽度) + 7 * 2 (左右padding值)

###不同属性值的含义

再来看看不同属性值所指代的含义:

1
2
3
4
5
6
7
8
9
10
11
12
<div id="contentBox" style="width: 200px;height: 100px;box-sizing: content-box;border: 5px solid #654321; margin: 20px 10px; padding: 7px;">
<div style="width: 250px;height: 50px;background: green">aaa</div>
</div>
```js
$contentBox = document.querySelector('#contentBox');
console.info('offsetWidth', '200(不含溢出的内容width)+ 7 * 2(内边距) + 5 * 2(边框)', $contentBox.offsetWidth); // 224
console.info('clientWidth', '200(不含溢出的内容width)+ 7 * 2 (内边距)- 滚动条宽度(if overflow-y == "scroll")', $contentBox.clientWidth); // 214
console.info('scrollWidth', '250(内容实际宽度) + 7(内边距)', $contentBox.scrollWidth); // 257

这里需要注意,当父容器加上overflow-y: scroll属性后,clientwidth会再减去15px的滚动条宽度(因不同系统不同浏览器而异)。同理overflow-x: scroll后高度也会减去15px(因不同系统不同浏览器而异)。

因此这三种属性可以理解为:

offsetWidth: 元素在页面布局中实际所占的宽度
clientWidth: 元素边框内部可视区域(不含溢出部分)的宽度
scrollWidth: 元素内容实际宽度(含溢出)

元素的位置

一般主要使用三个属性值:

offsetLeft: 元素外框相对于offsetParent的位置(父容器的offsetLeft为起点)
clientLeft: 元素内框(border内)对于外框的宽度,即边框border的宽度
scrollLeft: 元素滚动到的位置

so一般使用offsetLeftoffsetTop获取元素的位置。
需要注意,当元素父容器有css定位时(position),offsetParent返回一个指向最近的(closest,指包含层级上的最近)包含该元素的定位元素。如果没有定位的元素,则 offsetParent 为最近的 table 元素对象或根元素(标准模式下为 html;quirks 模式下为 body)。当元素的 style.display 设置为 “none” 时,offsetParent 返回 null。offsetParent 很有用,因为 offsetTop 和 offsetLeft 都是相对于其内边距边界的。

getBoundingClientRect

可用于返回改元素相对于视口的位置。

1
2
3
4
5
6
7
8
9
10
11
<div class="demo" style="position: absolute;left: 70px;margin-left: 100px;border: 5px solid green;width: 100%">
<div id="boderBox" style="position: absolute; top:100px;left:100px; width: 200px;height: 100px;border: 10px solid #ccc">
</div>
</div>
```js
$boderBox = document.querySelector('#boderBox');
var rectObject = $boderBox.getBoundingClientRect();
console.info('offsetLeft', '相对于父容器的位置', $boderBox.offsetLeft); // 100
console.info('rect-left', '相对于浏览器视口左上角的位置', rectObject.left); // 275