前言这篇文章主要介绍了有关浏览器中获取坐标以及尺寸的几种途径,算是比较全的一篇文章了.
在浏览器中获取元素的坐标以及尺寸是非常容易的,有非常多种方式来完成这些需求,但是杂乱的API和很多兼容处理导致了浏览器中没有直接的方式来获取我们想要的结果.
仔细想想这个问题,为什么浏览器并没有直接提供一个简单的属性就告诉你浏览器窗口的大小,或者一个元素的宽高.
就拿div元素来举例,我们有很多的问题影响到了元素宽高:
border 是否纳入宽高的计算?padding 是否纳入宽高的计算?magin 是否纳入宽高的计算?box-sizing:border-box; 时候该如何计算?父元素使用了overflow:hidden;把我们的元素裁剪了,这时候的宽高该如何计算?元素使用了overflow出现了滚动条此时该如何计算?而如果要获取一个浏览器窗口的大小,你还要面对我们到底是要获取哪个大小?
屏幕大小?浏览窗口大小?浏览区域大小?是否包含滚动条?当然最终你还要面临一个兼容问题,致我们敬爱的IE浏览器,不过本文可不探讨浏览器之间的差异.不过本文的涉及到的内容应该在IE9以上都是可以正常使用的(不过建议你还是查下can i use 或者MDN).
浏览器部分浏览器的宽高计算主要通过window对象来完成.
这个对象上提供了几个关键属性:
window.innerWidthwindow.innerHeightwindow.outerWidthwindow.outerHeight用人类语言来描述这几个属性就是.
属性名称人类解释innerWidth获取页面可视区域的宽度包括右侧的滚动条(如果有的话).所谓的可视区域就是HTML页面的内容区域不包括浏览器自身的ui所占用的空间(地址栏和菜单栏等).innerHeight获取页面可视区域的高度包括底部的滚动条(如果有的话).解释同上.outerWidth获取浏览器窗口宽度.outerHeight获取浏览器窗口高度.友情出演windows画图:
注意:单位均为px.
注意:滚动条并不视为浏览器的ui中的内容,而是视为内容区域的一部分,右侧默认的滚动条的宽度包含在window.innerWidth中,但是不属于html元素和html下的任何元素.
元素部分属性属性名称人类解释element.clientWidth元素内容区域宽度+padding的宽度,如果宽度溢出且裁剪那么不包含被裁剪掉的部分.element.scrollWidth当子元素宽度溢出,这里提供的是子元素的宽度包括溢出的部分,大小计算和clientWidth一样.element.offsetWidth相当于计算边框宽度的clientWidth,宽度计算为content+padding+border.element.clientHeight元素内容区域高度+padding的高度,如果高度溢出且裁剪那么不包含被裁剪掉的部分.element.scrollHeight当子元素高度溢出,这里提供的是子元素的高度包括溢出的部分,大小计算和clientHeight一样.element.offsetHeight相当于计算边框高度的clientHeight,高度计算为content+padding+border.element.clientLeft元素左边框的宽度element.scrollLeft计算较为复杂,看后续详解element.offsetLeft计算比较复杂,看下面详解element.clientTop元素上边框的宽度element.scrollTop计算较为复杂,看后续详解element.offsetTop计算比较复杂,看下面详解滚动条的规律无论是横向滚动条还是纵向滚动条,对于测量clientXXX这个单位来说是不包括滚动条的宽(高)的.
例如在下面这张图中我们进行测量父元素(黑色区域)的clientWidth结果和子元素(红色区域)的clientWidth的大小是一样的.
不过需要注意的是,一旦出现了滚动条对于clientWidth来说就意味着宽度减小(高度同理).
注意:图片所指的宽度是clientWidth
API名称是否包含滚动条大小offsetXXX包含clientXXX不包含scrollXXX不包含所以在margin:0;padding:0;border-width:0;情况下offsetWidth - clientWidth=滚动条的宽度.
通过这种方式我求出了chrome浏览器滚动条大小是17px整,但是不要忘记这些API只会返回整数.
注意:scrollXXX对于滚动条计算的规则和clientXXX表现一致.
含有box-sizing:border-box的计算请记住,对于clientXXX来说,元素的大小就是padding+content.
而使用border-box后元素的表现就是padding和border的修改就不会影响到元素的大小.
此时width是多少clientWidth就是多少,height同理.
但是不要忘记了边框不参与clientXXX的计算,所以border的修改并不会影响元素的宽高变化,那么那么当border变大,对应的clientXXX就变小.
一个元素设置了border-box:
box{ width:100px; padding:20px; border:20px solid; box-sizing:border-box;}此时clientWidth= 100px - 20px*2(左右边框的宽度) = 60px
由于offsetXXX的计算是包含border的大小的,所以如果一个元素设置了border-box那么offsetWidth就等于元素的width大小,因为border被限制到了width中.
offsetTop和offsetLeft子元素的offsetWidth|height是相对于父元素内容区域(padding+content)左侧和顶部的偏移量.
这个两个是相对值,是要求出向对于父级使用定位情况下来进行计算的,这个父元素可以通过HTMLElement.offsetParent来获取到.
例如:父级使用absolute或者relative.
注意:后文提出的父元素都指的是使用了相对定位的父元素.
注意:以上都是对于块级元素所描述的,对于行内元素或者td等元素相对的父元素不尽相同,这里不考虑这些情况,详情可以查看上方的链接.
情况1
在子元素使用了绝对定位的情况下,父元素无法干预子元素,所以子元素的scrollLeft就是left+margin-left.
情况2
第二种情况就是父元素和子元素都使用了相对定位,而相对定位是不脱离文档流的,那么父元素的padding-left就会影响到子元素的scrollLeft属性.
在线实例
注意:貌似offsetTop和Left在不同浏览器下有不同计算值,会带来兼容性问题,这里就不展开了,有兴趣的读者可以去查阅相关资料.
scrollTop和scrollLeft首先scrollTop和scrollLeft是一对可读写的属性,这意味着你可以获取他的值也可以设置它从而控制滚动的距离.
注意:scrollTop|scrollLeft是用在含有滚动区域的元素上(图中黑色边框的元素),而不是被滚动的元素上测量,被滚动的元素scrollTop永远是0.
简单理解:在垂直方向上含有滚动条的元素的内容区域的顶部(padding+content)相对于自身顶部边框的底部向上移动的距离(水平方向同理).
就是scrollTop的大小(图中超出去的部分).
元素方法getBoundingClientRect关于这个方法建议阅读MDN的指南.当然你也可以选择听我瞎扯几句.
这个api是ie首先提出(早在ie4时候就有了)的这也是ie对web开发的贡献之一.
调用这个api会返回一个DOMRect对象,这个对象多次易名,不过没有变化过基本概念.
...