元素大小和滚动
offset*
| 属性 | 说明 | 
|---|---|
elem.offsetWidth | 表示当前元素 border 及其以内的宽度 | 
elem.offsetHeight | 表示当前元素 border 及其以内的高度 | 
elem.offsetParent | 表示当前元素的包含块元素 | 
elem.offsetLeft | 表示当前元素相对应 offsetParent 的左偏移量 | 
elem.offsetTop | 表示当前元素相对应 offsetParent 的上偏移量 | 
offsetWidth 与 offsetHeight
这两个属性分别表示当前元素 border 及其以内的宽度和高度。
如果一个元素(或其任何祖先)具有 display:none 或不在文档中,则所有几何属性均为零(或 offsetParent 为 null)。
我们可以用它来检查一个元素是否被隐藏(宽高为0),像这样:
function isHidden(elem) {
  return !elem.offsetWidth && !elem.offsetHeight;
}

offsetLeft 与 offsetTop
一般用于绝对定位的元素,elem.offsetParent 就是该绝对定位元素的包含块。
其中 offsetLeft 和 offsetTop 就对应该绝对定位元素的 left 和 top。

important
有以下几种情况下,offsetParent 的值为 null:
- 对于未显示的元素(
display:none或者不在文档中) - 对于 
<body>与<html> - 对于带有 
position:fixed的元素 
client*
| 属性 | 说明 | 
|---|---|
elem.clientWidth | 元素 border 以内的宽度(不含 border) | 
elem.clientHeight | 元素 border 以内的高度(不含 border) | 
elem.clientLeft | 元素的左边 border 宽度,如果滚动条在左边,那么会加上滚动条宽度 | 
elem.clientTop | 元素的顶部 border 宽度 | 
这里注意一下 clientWidth 和 offsetWidth 的区别,前者是不包括元素边框宽度,后者要包含元素边框宽度。
scroll*
| 属性 | 说明 | 
|---|---|
elem.scrollWidth | 元素滚动内容的宽度 | 
elem.scrollHeight | 元素滚动内容的高度 | 
elem.scrollLeft | 滚动条左边离滚动框左边框的距离 | 
elem.scrollTop | 滚动条顶部离滚动框顶框的距离 | 
当没有出现滚动条时,scrollWidth 和 scrollHeight 就等于 clientWidth 和 clientHeight。
需要注意上面 offset* 和 client* 的所有属性都是 只读属性,但是 scroll* 中的 scrollLeft 和 scrollTop 是 可读写的,如果一个元素具有滚动条,那么你将其 scrollTop 赋值为 0,那么滚动条就会滚动到最顶部。
实践
实现 scrollBottom
如果没有滚动条,或元素底部已经完全滚动完成,那么它应该返回 0。
const scrollBottom = elem.scrollHeight - elem.clientHeight - elem.scrollTop;
将元素的滚动内容减去元素内部大小和滚出的上部分大小。
计算滚动条宽度
const scrollBarWidth = (elem.offsetWidth - elem.clientWidth) / 2 - elem.clientLeft;
getComputed(elem).width、clientWidth 和 offsetWidth 区别
getComputed(elem).width 的作用仅仅是获取该元素的 width 样式计算值,它会受到 box-sizing 等因素的影响。
clientWidth 和 offsetWidth 不会受到 box-sizing 的影响,这两个是获取的元素具体在页面中的几何尺寸,前者是 padding 及其以内,后者是 border 及其以内。