获取DOM元素的位置和尺寸
缘由
在CSS中,每一个元素都是一个盒子,都有着描述盒子大小和位置的相关属性。比如:width, height, position: trbl(top, right, bottom, left)。在实际开发中,我们可能需要通过JavaScript来获取它们的位置和尺寸关系,这篇笔记就是记录这个问题,不瞎BB了, 我们直接进入正题。
1. DOM

查看各浏览器版本是否兼容属性: Can I Use
Scroll家族


scrollscrollHeight: 只读- 返回
Number表示元素的滚动视图高度, 包括由于溢出而无法展示在网页的不可见部分。 scrollHeight>=clientHeight- 无滚动条:
scrollHeight=clientHeight=height+padding-top+padding-bottom - 有水平滚动条:
scrollHeight=clientHeight+horizontal scroll bar=height+padding-top+padding-bottom+horizontal scroll bar
- 返回
scrollWidth: 只读- 返回
Number表示元素的滚动视图宽度, 包括由于溢出而无法展示在网页的不可见部分。 scrollWidth>=clientWidth- 无滚动条:
scrollWidth=clientWidth=width+padding-left+padding-right - 有垂直滚动条:
scrollWidth=clientWidth+vertical scroll bar=width+padding-left+padding-right+vertical scroll bar
- 返回
scrollTop: 可读可写- 返回
Number表示该元素纵向滚动条距离
- 返回
scrollLeft: 可读可写- 返回
Number表示该元素横向滚动条距离最左的位移.
- 返回
getBoundingClientRect(): 返回元素的大小及其相对于视口的位置。

判定元素是否滚动到底
如果元素滚动到底,下面等式返回true,没有则返回false.
element.scrollHeight - element.scrollTop === element.clientHeight
当容器不滚动但有溢出的子容器时,这些检查可以确定容器能否滚动:
window.getComputedStyle(element).overflowY === 'visible' window.getComputedStyle(element).overflowY !== 'hidden'
Client家族

clientclientHeight: 只读- 返回
Number表示内部相对于外层元素的高度. clientHeight=height+padding-top+padding-bottom-horizontal scroll bar(?)
- 返回
clientWidth: 只读- 返回
Number表示该元素它内部的宽度. clientWidth=width+padding-left+padding-right-vertical scroll bar(?)
- 返回
clientTop: 只读- 返回
Number表示该元素距离它上边界的高度. clientTop=border-top+ 上边的滚动条大小
- 返回
clientLeft: 只读- 返回
Number表示该元素距离它左边界的宽度. clientLeft=border-left+ 左边 的滚动条大小
- 返回
Note: (?) 是否存在
Offset家族

#content {
width: 300px;
height: 200px;
border: 25px;
padding: 20px;
}

offsetoffsetHeight- 返回
double, 高度包含该元素的垂直内边距(padding-top,padding-bottom)和边框(border-top,border-bottom)。 offsetHeight=height(含滚动条宽度)+border-top+border-bottom+padding-top+padding-bottom.
- 返回
offsetWidth- 返回
double, 高度包含该元素的水平内边距(padding-left,padding-right)和边框(border-left,border-right)。 offsetWidth=width(含滚动条宽度)+border-left+border-right+padding-left+padding-right.
- 返回
offsetTop- 返回
double,当前元素border顶部距离父元素顶部或者body元素border顶部的距离。 offsetTop=marginTop?+paddingTop?+top(先找到offsetParent)
- 返回
offsetLeft- 返回
double, 当前元素的border左边距离父元素border左边或者body元素border左边的距离。 offsetLeft=marginLeft?+paddingLeft?+left(先找到offsetParent)
- 返回
offsetParent- 返回
HTMLElement, 返回一个指向最近的(closest,指包含层级上的最近), 包含该元素的定位元素,如果没有就是body元素。当元素的style.display设置为none时,offsetParent返回null。(与当前元素最近的经过定位(position不等于static)的父级元素)
- 返回
定义
offsetParent情况:1、
position: fixed->offsetParent = null

2 父元素是根据其父元素定位后元素,当前元素无定位 ->
offsetParent = current parent dom

3 父元素是无定位后元素,当前元素无定位 ->
offsetParent = <body></body>

4
display: none->offsetParent = null

5
<body></body>元素 ->offsetParent = null
注意:
- 1、需要考虑盒模型,即
box-sizing属性对元素的影响; - 2、需要考虑到
overflow或者内容撑开出现的滚动条; - 3、有些高度是有内容自动撑开的,即设置
width、height为auto。
获取元素位置
function getPosition(el) {
var _x = 0;
var _y = 0;
while (el) {
if (el.tagName.toUpperCase() == "BODY") {
// deal with browser quirks with body/window/document and page scroll
var xScroll = el.scrollLeft || document.documentElement.scrollLeft;
var yScroll = el.scrollTop || document.documentElement.scrollTop;
_x += (el.offsetLeft - xScroll + el.clientLeft);
_y += (el.offsetTop - yScroll + el.clientTop);
} else {
// for all other non-BODY elements
_x += (el.offsetLeft - el.scrollLeft + el.clientLeft);
_y += (el.offsetTop - el.scrollTop + el.clientTop);
}
el = el.offsetParent;
}
return {
x: _x,
y: _y
};
}
/ deal with the page getting resized or scrolled
window.addEventListener("scroll", updatePosition, false);
window.addEventListener("resize", updatePosition, false);
function updatePosition() {
// add your code to update the position when your browser
// is resized or scrolled
var position = getPosition(myElement);
}
参考: