element.getBoundingClientRect().width/height VS. element.offsetWidth/offsetHeight VS. element.client

Posted linweinb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了element.getBoundingClientRect().width/height VS. element.offsetWidth/offsetHeight VS. element.client相关的知识,希望对你有一定的参考价值。

获得元素尺寸可谓多种多样,但通常它们是有一定区别的。

先说说元素的getBoundingClientRect()方法,这个方法的width或height属性可以计算元素尺寸,但width或height除了本身的content的宽高之外还包括padding和border的部分,这里不得不说的一个属性就是元素的offsetWidth和offsetHeight属性,这俩属性和getBoundingClientRect()的width和height属性极其相似,也是包含padding和border的部分,但是在有转换比如缩放元素的时候这两者就不一样了,我这里有一个div元素,CSS样式如下:

div{
        width:200px;
        height:200px;
        transform:scale(0.5); /*缩小0.5倍*/
        background:red;
}

这时就体现出两者的区别了:

var div=document.getElementsByTagName("div")[0];

console.log(div.getBoundingClientRect().width,div.getBoundingClientRect().height);

console.log(div.offsetWidth,div.offsetHeight);

输出如下:

技术分享图片

你看,getBoundingClientRect()的width和height都是以页面实际渲染的尺寸进行计算的,缩小渲染的尺寸相应也会缩小(近似等于100px,居然有误差!!),不管CSS的width或height属性是什么,但offsetWidth和offsetHeight却是始终以CSS属性返回元素的尺寸(都是200px),不管缩不缩放(真是冥顽不化.jpg)。

另一个与getBoundingClientRect().width/height和offsetWidth/offsetHeight相似的就是元素的clientWidth和clientHeight属性了,但这玩意儿与它俩不同的是它并不包括border部分,只包含content部分和padding部分,注意,在有滚动条的情况下clientWidth和clientHeight不包含滚动条,换句话说就是在有滚动条的情况下只包含滚动条内部的可视部分,盗用MDN上的图片如下:

技术分享图片

clientWidth和clientHeight通常用来计算视口尺寸:

function getViewportSize(){
    return document.compatMode==="CSS1Compat"?{     // 标准模式
        width:document.documentElement.clientWidth,
        height:document.documentElement.clientHeight
    }:{   // 怪异模式
        width:document.body.clientWidth,
        height:document.body.clientHeight
    };
}

另外,MDN上明确讲明:

The Element.clientWidth property is zero for elements with no CSS or inline layout boxes.

The Element.clientHeight read-only property is zero for elements with no CSS or inline layout boxes.

也就是如果该元素是没有CSS样式的或本身是内联元素,则这两个属性都是0,这里我就只实验了span元素:

<span>lala</span>

输出如下:

技术分享图片

你看,即使span元素里面有content,两者依然为0。

clientWidth和clientHeight只能计算可视的部分,它不包含溢出可视区域的部分,如果要包含溢出可视区域的部分,就要用到元素的scrollWidth和scrollHeight属性,如果没有溢出部分,scrollWidth和scrollHeight是和clientWidth和clientHeight相等的。MDN对于scrollWidth和scrollHeight的描述分别如下:

The Element.scrollWidth read-only property is a measurement of the width of an element‘s content, including content not visible on the screen due to overflow.

The Element.scrollHeight read-only property is a measurement of the height of an element‘s content, including content not visible on the screen due to overflow.

也就是两者包括由于溢出导致屏幕上不可见的部分都计算在内,这个元素会返回元素的整个内容加上padding的尺寸(当然,和clientWidth和clientHeight一样包含padding而不包含border),MDN举了一个例子:

For example, if a 600x400 pixel element is being displayed inside a 300x300 pixel scrollbox, scrollWidth will return 600 while scrollHeight will return 400.

也就是如果一个元素尺寸是width为600px,height为400px,显示在一个宽高都为300px的含有滚动条的框内,scrollWidth返回600而scrollHeight返回400。

我这里还是使用div元素,CSS样式如下:

div{
       width:200px;
       height:200px;
       overflow:scroll;
}

输出如下:

技术分享图片

由于换行的缘故,元素并没有横向溢出可视区域,而纵向溢出了很多,466px远远大于200px。

以上是关于element.getBoundingClientRect().width/height VS. element.offsetWidth/offsetHeight VS. element.client的主要内容,如果未能解决你的问题,请参考以下文章