在一些复杂的页面中经常会用JavaScript处理一些DOM元素的动态效果,这种时候我们经常会用到一些元素位置和尺寸的计算,浏览器兼容性问题也是不可忽略的一部分,要想写出预想效果的JavaScript代码,我们需要了解一些基本知识。

基础概念

为了方便理解,我们需要了解几个基础概念,每个HTML元素都有下列属性

offsetWidth

clientWidth

scrollWidth

offsetHeight

clientHeight

scrollHeight

offsetLeft

clientLeft

scrollLeft

offsetTop

clientTop

scrollTop

为了理解这些属性,我们需要知道HTML元素的实际内容有可能比分配用来容纳内容的盒子更大,因此可能会出现滚动条,内容区域是视口,当实际内容比视口大的时候,需要把元素的滚动条位置考虑进去。

1. clientHeight和clientWidth用于描述元素内尺寸,是指 元素内容+内边距 大小,不包括边框(IE下实际包括)、外边距、滚动条部分

2. offsetHeight和offsetWidth用于描述元素外尺寸,是指 元素内容+内边距+边框,不包括外边距和滚动条部分

3. clientTop和clientLeft返回内边距的边缘和边框的外边缘之间的水平和垂直距离,也就是左,上边框宽度

4. offsetTop和offsetLeft表示该元素的左上角(边框外边缘)与已定位的父容器(offsetParent对象)左上角的距离

5. offsetParent对象是指元素最近的定位(relative,absolute)祖先元素,递归上溯,如果没有祖先元素是定位的话,会返回null

写个小例子方便理解

  1. <div id="divParent" style="padding: 8px; position: relative;">
  2. <div id="divDisplay" style="background-color: #0f0; margin: 30px; padding: 10px;
  3. height: 200px; width: 200px; border: solid 3px #f00;">
  4. </div>
  5. </div>
  1. <script type="text/javascript">
  2. var div = document.getElementById('divDisplay');
  3.  
  4. var clientHeight = div.clientHeight;
  5. var clientWidth = div.clientWidth;
  6. div.innerHTML += 'clientHeight: ' + clientHeight + '<br/>';
  7. div.innerHTML += 'clientWidth: ' + clientWidth + '<br/>';
  8.  
  9. var clientLeft = div.clientLeft;
  10. var clientTop = div.clientTop;
  11. div.innerHTML += 'clientLeft: ' + clientLeft + '<br/>';
  12. div.innerHTML += 'clientTop: ' + clientTop + '<br/>';
  13.  
  14. var offsetHeight = div.offsetHeight;
  15. var offsetWidth = div.offsetWidth;
  16. div.innerHTML += 'offsetHeight: ' + offsetHeight + '<br/>';
  17. div.innerHTML += 'offsetWidth: ' + offsetWidth + '<br/>';
  18.  
  19. var offsetLeft = div.offsetLeft;
  20. var offsetTop = div.offsetTop;
  21. div.innerHTML += 'offsetLeft: ' + offsetLeft + '<br/>';
  22. div.innerHTML += 'offsetTop: ' + offsetTop + '<br/>';
  23.  
  24. var offsetParent = div.offsetParent;
  25. div.innerHTML += 'offsetParent: ' + offsetParent.id + '<br/>';
  26. </script>

效果如图

从图中我们可以看到,clientHeight就是div的高度+上下各10px的padding,clientWidth同理

而clientLeft和ClientTop即为div左、上边框宽度

offsetHeight是clientHeight+上下个3px的边框宽度之和,offsetWidth同理

offsetTop是div 30px的 maggin+offsetparent 8px的 padding,offsetLeft同理

6. scrollWidth和scrollHeight是元素的内容区域加上内边距加上溢出尺寸,当内容正好和内容区域匹配没有溢出时,这些属性与clientWidth和clientHeight相等

7. scrollLeft和scrollTop是指元素滚动条位置,它们是可写

下面写个简单例子理解

  1. <div id="divParent" style=" padding:8px; border:solid 7px #000; height:200px; width:500px; overflow:auto;">
  2. <div id="divDisplay" style="background-color: #0f0; margin: 30px; padding: 10px;
  3. height: 400px; width: 200px; border: solid 3px #f00;">
  4. </div>
  5. </div>
  1. <script type="text/javascript">
  2. var divP = document.getElementById('divParent');
  3. var divD = document.getElementById('divDisplay');
  4.  
  5. var scrollHeight = divP.scrollHeight;
  6. var scrollWidth = divP.scrollWidth;
  7. divD.innerHTML += 'scrollHeight: ' + scrollHeight + '<br/>';
  8. divD.innerHTML += 'scrollWidth: ' + scrollWidth + '<br/>';
  9. </script>

在FireFox和IE10(IE10以下版本盒模型和W3C标准不一致,不加讨论,兼容性问题下面会介绍到)下得到结果scrollHeight: 494,而在Chrome和Safari下得到结果scrollHeight: 502,差了8px,根据8可以简单推测是divParent的padding,来算一下是不是

我们可以看看它们的结果是怎么来的,首先scrollHeight肯定包含了divDisplay所需的高度 400px的高度+上下各10px的padding+上下各3px的border+上下各30px的margin,这样

400+10*2+3*2+30*2=486

这样486+8=494, 486+8*2=502果真是这样,在FireFox和IE10下没有计算下padding

有了这些基础知识后,我们就可以计算元素的位置和尺寸了。

相对于文档与视口的坐标

当我们计算一个DOM元素位置也就是坐标的时候,会涉及到两种坐标系,文档坐标视口坐标

我们经常用到的document就是整个页面部分,而不仅仅是窗口可见部分,还包括因为窗口大小限制而出现滚动条的部分,它的左上角就是我们所谓相对于文档坐标的原点。

视口是显示文档内容的浏览器的一部分,它不包括浏览器外壳(菜单,工具栏,状态栏等),也就是当前窗口显示页面部分,不包括滚动条。

如果文档比视口小,说明没有出现滚动,文档左上角和视口左上角相同,一般来讲在两种坐标系之间进行切换,需要加上或减去滚动的偏移量(scroll offset)。

为了在坐标系之间进行转换,我们需要判定浏览器窗口的滚动条位置。window对象的pageXoffset和pageYoffset提供这些值,IE 8及更早版本除外。也可以通过scrollLeft和scrollTop属性获得滚动条位置,正常情况下通过查询文档根节点(document.documentElement)来获得这些属性值,但在怪异模式下必须通过文档的body上查询。

  1. function getScrollOffsets(w) {
  2. var w = w || window;
  3. if (w.pageXoffset != null) {
  4. return { x: w.pageXoffset, y: pageYoffset };
  5. }
  6. var d = w.document;
  7. if (document.compatMode == "CSS1Compat")
  8. return { x: d.documentElement.scrollLeft, y: d.documentElement.scrollTop };
  9. return { x: d.body.scrollLeft, y: d.body.scrollTop };
  10. }

有时候能够判断视口的尺寸也是非常有用的

  1. function getViewPortSize(w) {
  2. var w = w || window;
  3. if (w.innerWidth != null)
  4. return { w: w.innerWidth, h: w.innerHeight };
  5. var d = w.document;
  6. if (document.compatMode == "CSS1Compat")
  7. return { w: d.documentElement.clientWidth, h: d.documentElement.clientHeight };
  8. return { w: d.body.clientWidth, h: d.body.clientHeight };
  9. }

文档坐标

任何HTML元素都拥有offectLeft和offectTop属性返回元素的X和Y坐标,对于很多元素,这些值是文档坐标,但是对于以定位元素后代及一些其他元素(表格单元),返回相对于祖先的坐标。我们可以通过简单的递归上溯累加计算

  1. function getElementPosition(e) {
  2. var x = 0, y = 0;
  3. while (e != null) {
  4. x += e.offsetLeft;
  5. y += e.offsetTop;
  6. e = e.offsetParent;
  7. }
  8. return { x: x, y: y };
  9. }

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

视口坐标

计算视口坐标就相对简单了很多,可以通过调用元素getBoundingClientRect方法。方法返回一个有left、right、top、bottom属性的对象,分别表示元素四个位置的相对于视口的坐标。getBoundingClientRect所返回的坐标包含元素的内边距和边框,不包含外边距。兼容性很好,非常好用

元素尺寸

由上面计算坐标方法,我们可以方便得出元素尺寸。在符合W3C标准的浏览器中getBoundingClientRect返回的对象还包括width和height,但在原始IE中未实现,但是通过返回对象的right-left和bottom-top可以方便计算出。

JavaScript获取DOM元素位置和尺寸大小的更多相关文章

  1. 获取DOM元素位置和尺寸大小

    JavaScript获取DOM元素位置和尺寸大小 在一些复杂的页面中经常会用JavaScript处理一些DOM元素的动态效果,这种时候我们经常会用到一些元素位置和尺寸的计算,浏览器兼容性问题也是不可忽 ...

  2. javascript中获取dom元素的高度和宽度

    javascript中获取dom元素高度和宽度的方法如下: 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网 ...

  3. javascript中获取dom元素高度和宽度

    javascript中获取dom元素高度和宽度的方法如下: 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网 ...

  4. js | javascript中获取dom元素的高度和宽度

    javascript中获取dom元素高度和宽度的方法如下: 网页可见区域宽: document.body.clientWidth网页可见区域高: document.body.clientHeight网 ...

  5. vue 组件传递值以及获取DOM元素的位置信息

    1.父组件 select_li.vue 1.1 父组件模板 <template> <div id='selectLi' ref="selectLi"> &l ...

  6. Vue自定义指令获取DOM元素

    我们知道,Vue.js的核心是数据驱动,当数据有所变化时,DOM就会被更新,比如: <span v-text="msg"></span> export de ...

  7. vue(4)—— vue的过滤器,监听属性,生命周期函数,获取DOM元素

    过滤器 vue允许自定义过滤器,我个人认为,过滤器有两种,一种是对数据的清洗过滤,一种是对数据切换的动画过滤 数据切换的动画过滤 这里还是利用前面的动态组件的例子: 这里由于没办法展示动画效果,代码如 ...

  8. 用javaScript获取页面元素值

    用JavaScript获取页面元素常见的三种方法:                                                           getElementById() ...

  9. 通过class和id获取DOM元素的区别

    1.通过id获取DOM元素的方法:document.getElementById("id名") 2.通过class获取DOM元素的方法:document.getElementsBy ...

随机推荐

  1. tomcat设置内存大小

    -Xms256m -Xmx512m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

  2. LeetCode-Data Stream as Disjoint Intervals

    Given a data stream input of non-negative integers a1, a2, ..., an, ..., summarize the numbers seen ...

  3. 团队开发——Alpha版总结会议

    本组目前存在的问题: 1.在选题的时候,题目选的比较有难度,造成后期工作量较大,实现有难度(未能正确估计项目的难度). 2.最初规划时,设计的功能较多,但是技术水平达不到,导致目前完成功能较少. 3. ...

  4. iOS多线程自定义operation加载图片 不重复下载图片

    摘要:1:ios通过抽象类NSOperation封装了gcd,让ios的多线程变得更为简单易用:   2:耗时的操作交给子线程来完成,主线程负责ui的处理,提示用户的体验   2:自定义operati ...

  5. Node.js 项目搭建

    关于 本书致力于教会你如何用Node.js来开发应用,过程中会传授你所有所需的“高级”JavaScript知识.本书绝不是一本“Hello World”的教程. 状态 你正在阅读的已经是本书的最终版. ...

  6. 1564: [NOI2009]二叉查找树 - BZOJ

    Description Input Output只有一个数字,即你所能得到的整棵树的访问代价与额外修改代价之和的最小值.Sample Input4 101 2 3 41 2 3 41 2 3 4Sam ...

  7. codeforces399D

    题目大意:ainta刷一面n*n的二维墙.墙一开始可能有一些块被刷了.他终止刷墙的前提是墙的每一行每一列都至少有一块被刷.他每一次从n*n的墙随机选择一块,如果这一块没有被刷就刷,刷了就无视,刷墙不计 ...

  8. 开发EXTMVC框架前需要了解的基础知识整理

    1.组件选择器 目的:了解如何选择Extjs中的组件,就跟学习jquery时一定会先要学习:$()选择器一样. 常用场景:       1.在controller中的control事件中用到      ...

  9. boost之bind,function,signal总结

    boost里的bind,function,signal三个组件都是对用函数做参数(其他算法也用函数做参数),对函数的某一项进行操作. bind主要是对函数参数的作用. function主要是对函数地址 ...

  10. zoj 2760 How Many Shortest Path 最大流

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1760 Given a weighted directed graph ...