Skip to main content

获取DOM元素的位置和尺寸

缘由

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

1. DOM

dom-size-position

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

Scroll家族

scroll-position-1

scroll-position-2

  • scroll
    • scrollHeight: 只读
      • 返回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(): 返回元素的大小及其相对于视口的位置。

getBoundingClientRect-trbl

判定元素是否滚动到底

如果元素滚动到底,下面等式返回true,没有则返回false.

element.scrollHeight - element.scrollTop === element.clientHeight

当容器不滚动但有溢出的子容器时,这些检查可以确定容器能否滚动:

window.getComputedStyle(element).overflowY === 'visible' window.getComputedStyle(element).overflowY !== 'hidden'

Client家族

client-position

  • client
    • clientHeight: 只读
      • 返回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家族

dom-offset

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

window-scroll

  • offset

    • offsetHeight
      • 返回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

      fix-position-dom

      display-none-offsetParent

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

      parent-position-dom

      parent-position-offsetParent

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

      parent-none-position-dom

      parent-none-position-offsetParent

    • 4 display: none -> offsetParent = null

      display-none-dom

      display-none-offsetParent

    • 5 <body></body>元素 -> offsetParent = null

      body-offsetParent

    注意

    • 1、需要考虑盒模型,即box-sizing属性对元素的影响;
    • 2、需要考虑到overflow或者内容撑开出现的滚动条;
    • 3、有些高度是有内容自动撑开的,即设置widthheightauto

获取元素位置

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);
}

参考:

MDN - Element

DOM系列:获取元素位置和尺寸

JavaScript学习笔记:视口宽高、位置与滚动高度

Get an Element's Position Using JavaScript