JS 获取 dom 的尺寸和位置总结

Author Avatar
Crown 9月 22, 2017
  • 在其它设备中阅读本文章

相信每个人在刚接触 JS 时, 在遇到关于 dom 的各种位置与尺寸这一块相关方法时, 被会被搞混, 这里我想系统的整理一下关于这一块的知识, 也方便日后的查询.

css 中的 width 和 height

关于这个想必大家应该也了解的差不多了,一般我们要注意的特殊情况大致有以下两种就行了

  • box-sizing的设置

默认的有两个关键字, content-box 是默认值,此时 width 只表示内容 content,border-box 表示元素的 width 等于 content + padding + border 三者之和。border-box 相对就非常有用了,尤其当我们在使用 100% 来规定宽高的时候. 关于这个基础知识我就不再多说了.

  • 默认滚动轴的占宽

这个相对了解清楚的人就比较少了, 当把content + padding + border + margin加在一起时显示的才是一个完整的 dom, 但是当里面的内容超过限制时便会出现滚动轴, 而滚动轴默认是占用padding的空间, 当padding的宽度小于滚动条, 那么滚动条多出来的部分将占用content的宽度.

JS获取元素的尺寸

有了上面的基础, 下面的知识就更好开展了, 但我们去用 JS 获取元素的长宽时, 前万不要用element.style.width这种方式来取, 这种方法默认取的是 css 中的元素样式, 没有你给 element 没有设置宽高, 这个值默认是null, 这个你直接在控制台中console.log(element.style)就可以看到, 如果你给他设置了宽高, 那么这个值才取得到值.

如果你真要通过除了 offset 等之外方法来获取 dom 的真实尺寸, 这里其实还有个其他JS方法来获取element真实的尺寸 — getBoundingClientRect, 附上 MDN 链接, 这个属性主要是用来计算元素距离视口的距离的, 但是里面会有 widthheight 两个属性, 如下所示:

接下来我们来好好识别下这几种属性的区别

Column AColumn BColumn CColumn D
offsetWidthoffsetHeightoffsetLeftoffsetTop
clientWidthclientHeightclientLeftclientTop
scrollWidthscrollHeightscrollLeftscrollTop
  1. clientHeightclientWidth用于描述元素内尺寸,是指 元素内容+内边距 大小,不包括边框(IE下实际包括)、外边距、滚动条部分
  2. offsetHeightoffsetWidth用于描述元素外尺寸,是指 元素内容+内边距+边框,不包括外边距和滚动条部分
  3. clientTopclientLeft返回内边距的边缘和边框的外边缘之间的水平和垂直距离,也就是左,上边框宽度
  4. offsetTopoffsetLeft表示该元素的左上角(边框外边缘)与已定位的父容器(offsetParent对象)左上角的距离
  5. offsetParent对象是指元素最近的定位(relative,absolute)祖先元素,递归上溯,如果没有祖先元素是定位的话,会返回null

这里我们看个简单的例子就知道了

//html
<div id="divParent" style="padding: 8px; background-color: #aaa; position: relative;">
  <div id="divDisplay" style="background-color: #0f0; margin: 30px; padding: 10px;
            height: 200px; width: 200px; border: solid 3px #f00;">
  </div>
</div>
//js
var div = document.getElementById('divDisplay');

var clientHeight = div.clientHeight;
var clientWidth = div.clientWidth;
div.innerHTML += 'clientHeight: ' + clientHeight + '<br/>';
div.innerHTML += 'clientWidth: ' + clientWidth + '<br/>';

var clientLeft = div.clientLeft;
var clientTop = div.clientTop;
div.innerHTML += 'clientLeft: ' + clientLeft + '<br/>';
div.innerHTML += 'clientTop: ' + clientTop + '<br/>';

var offsetHeight = div.offsetHeight;
var offsetWidth = div.offsetWidth;
div.innerHTML += 'offsetHeight: ' + offsetHeight + '<br/>';
div.innerHTML += 'offsetWidth: ' + offsetWidth + '<br/>';

var offsetLeft = div.offsetLeft;
var offsetTop = div.offsetTop;
div.innerHTML += 'offsetLeft: ' + offsetLeft + '<br/>';
div.innerHTML += 'offsetTop: ' + offsetTop + '<br/>';

var offsetParent = div.offsetParent;
div.innerHTML += 'offsetParent: ' + offsetParent.id + '<br/>';

效果图展示:

  1. scrollWidthscrollHeight是元素的内容区域加上内边距加上溢出尺寸,当内容正好和内容区域匹配没有溢出时,这些属性与clientWidthclientHeight相等
  2. scrollLeftscrollTop是指元素滚动条位置,它们是可写

我们可以从上面的知识点延伸出一个小技巧, 如何利用offsetXXX来计算 element 相对于目标父级元素的位置, 也就是我们的文档坐标, 方法如下:

function getElementPosition(e) {
    var x = 0,
        y = 0;
    while (e != null) {
        x += e.offsetLeft;
        y += e.offsetTop;
        e = e.offsetParent;
    }
    return {
        x: x,
        y: y
    };
}

尽管如此,这个函数也不总是计算正确的值,当文档中含有滚动条的时候这个方法就不能正常工作了,我们只能在没有滚动条的情况下使用这个方法,不过我们用这个原理算出一些元素相对于某个父元素的坐标。

有了文档坐标, 那我们的视口坐标如何计算呢? 其实很简单, 我们在上面提到过的一个函数已经介绍过这块知识了, 可以通过调用元素的getBoundingClientRect方法。方法返回一个有leftrighttopbottom属性的对象,分别表示元素四个位置的相对于视口的坐标。getBoundingClientRect所返回的坐标包含元素的内边距和边框,不包含外边距。兼容性很好,非常好用.


随着我自己个人的技术水平的提高,我也会尽最大力量去原创一些有价值有内容的文章出来。在此期间我的文章会同步更新在以下地方,欢迎大家在自己长逛的网站中关注或者star我的Github来了解我的最新消息!!!推荐大家收藏关注我的博客网站crowncj.com,因为我的最新更改与文章只会在这里更新,其他地方**的文章可能会存在更新不及时或者忘记更新等问题。

未经允许,不准转载