javascript好文---深入理解定位父级offsetParent及偏移大小
前面的话
偏移量(offset dimension)是javascript中的一个重要的概念。涉及到偏移量的主要是offsetLeft、offsetTop、offsetHeight、offsetWidth这四个属性。当然,还有一个偏移参照——定位父级offsetParent。本文将详细介绍该部分内容
offsetParent定位父级
在理解偏移大小之前,首先要理解offsetParent。人们并没有把offsetParent翻译为偏移父级,而是翻译成定位父级,很大原因是offsetParent与定位有关
定位父级offsetParent的定义是:与当前元素最近的经过定位(position不等于static)的父级元素,主要分为下列几种情况 :
【1】元素自身有fixed定位,offsetParent的结果为null
当元素自身有fixed固定定位时,我们知道固定定位的元素相对于视口进行定位,此时没有定位父级,offsetParent的结果为null
[注意]firefox浏览器有兼容性问题
<div id="test" style="position:fixed"></div> <script> //firefox并没有考虑固定定位的问题,返回<body>,其他浏览器都返回null console.log(test.offsetParent); </script>
【2】元素自身无fixed定位,且父级元素都未经过定位,offsetParent的结果为<body>
<div id="test"></div> <script> console.log(test.offsetParent);//<body> </script>
【3】元素自身无fixed定位,且父级元素存在经过定位的元素,offsetParent的结果为离自身元素最近的经过定位的父级元素
<div id="div0" style="position:absolute;"><div id="div1" style="position:absolute;"><div id='test'></div> </div> </div> <script> console.log(test.offsetParent); //<div id="div1"> </script>
【4】<body>元素的parentNode是null
console.log(document.body.offsetParent);//null
IE7-浏览器Bug
对于定位父级offsetParent来说,IE7-浏览器存在以下bug
【bug1】当元素本身经过绝对定位或相对定位,且父级元素无经过定位的元素时,IE7-浏览器下,offsetParent是<html>
<div id="test" style="position:absolute;"></div> <script> //IE7-浏览器返回<html>,其他浏览器返回<body> console.log(test.offsetParent); </script>
<div id="test" style="position:relative;"></div> <script> //IE7-浏览器返回<html>,其他浏览器返回<body> console.log(test.offsetParent); </script>
<div id="test" style="position:fixed;"></div> <script> //firefox并没有考虑固定定位的问题,返回<body>,其他浏览器都返回null console.log(test.offsetParent); </script>
【bug2】如果父级元素存在触发haslayout的元素或经过定位的元素,且offsetParent的结果为离自身元素最近的经过定位或触发haslayout的父级元素
[注意]关于haslayout的详细信息移步至此
<div id="div0" style="display:inline-block;"><div id='test'></div> </div> <script> //IE7-浏览器返回<div id="div0">,其他浏览器返回<body> console.log(test.offsetParent); </script>
<div id="div0" style="position:absolute;"><div id="div1" style="display:inline-block;"><div id='test'></div> </div> </div> <script> //IE7-浏览器返回<div id="div1">,其他浏览器返回<div id="div0"> console.log(test.offsetParent); </script>
<div id="div0" style="display:inline-block;"><div id="div1" style="position:absolute;"><div id='test'></div> </div> </div> <script> //所有浏览器都返回<div id="div1"> console.log(test.offsetParent); </script>
偏移量
偏移量共包括offsetHeight、offsetWidth、offsetLeft、offsetTop这四个属性
offsetWidth
offsetWidth表示元素在水平方向上占用的空间大小,无单位(以像素px计)
offsetWidth = border-left-width + padding-left + width + padding-right + border-right-width;
offsetHeight
offsetHeight表示元素在垂直方向上占用的空间大小,无单位(以像素px计)
offsetHeight = border-top-width + padding-top + height + padding-bottom + border-bottom-width
<div id="test" style="width:100px; height:100px; padding:10px; margin:10px; border:1px solid black;"></div> <script> //122=1+10+100+10+1 console.log(test.offsetWidth); console.log(test.offsetHeight); </script>
[注意]如果存在垂直滚动条,offsetWidth也包括垂直滚动条的宽度;如果存在水平滚动条,offsetHeight也包括水平滚动条的高度
<div id="test" style="width:100px; height:100px; padding:10px; margin:10px; border:1px solid black; overflow: scroll;"></div> <script> //IE8-浏览器将垂直滚动条的宽度计算在width宽度和height高度中,width和height的值仍然是100px; //而其他浏览器则把垂直滚动条的宽度从width宽度中移出,把水平滚动条的高度从height高度中移出,则滚动条宽度为17px,width宽度和height高度为剩下的83pxif(window.getComputedStyle){console.log(getComputedStyle(test).width,getComputedStyle(test).height)//83px }else{console.log(test.currentStyle.width,test.currentStyle.height);//100px } //122=1+10+100+10+1 console.log(test.offsetWidth,test.offsetHeight); </script>
offsetTop
offsetTop表示元素的上外边框至offsetParent元素的上内边框之间的像素距离
offsetLeft
offsetLeft表示元素的左外边框至offsetParent元素的左内边框之间的像素距离
<div id="out" style="padding: 5px;position: relative;background-color: pink;margin: 10px;"><div id="test" style="width:100px; height:100px; margin:10px;background-color:green;"></div> </div> <script> //15=test.marginTop(10) + out.paddingTop(5) alert(test.offsetTop);alert(test.offsetParent) //15=test.marginLeft(10) + out.paddingLeft(5) alert(test.offsetLeft); </script>
IE7-Bug
IE7-浏览器在offsetTop属性的处理上存在bug
【1】若父级设置position: relative,则IE7-浏览器下无法阻止margin传递现象,offsetTop值为offsetParent元素的paddingBottom值
<div id="out" style="padding: 5px;position: relative;"><div id="test" style="width:100px; height:100px; margin:10px;"></div> </div> <script> //其他浏览器返回15(5+10),而IE7-浏览器返回5 console.log(test.offsetTop); </script>
【2】若父级设置position: aboslute(或其他触发haslayout的条件),offsetTop值为offsetParent元素的paddingBottom值和当前元素的marginTop值的较大值
<div id="out" style="padding: 5px;position:absolute;"><div id="test" style="width:100px; height:100px; margin:10px;"></div> </div> <script> //其他浏览器返回15(5+10),而IE7-浏览器返回10(10和5的较大值) console.log(test.offsetTop); </script>
页面偏移
要知道某个元素在页面上的偏移量,将这个元素的offsetLeft和offsetTop与其offsetParent的相同属性相加,并加上offsetParent的相应方向的边框,如此循环直到根元素,就可以得到元素到页面的偏移量
[注意]在默认情况下,IE8-浏览器下<html>和<body>的边框宽度都是medium,而其他浏览器是0px
html,body{border: 0;} body{margin:0;}
function getCSS(obj,attr){if(window.getComputedStyle){return getComputedStyle(obj)[attr];}return obj.currentStyle[attr]; }
function getElementLeft(element){var actualLeft = element.offsetLeft;var current = element.offsetParent;while(current != null){actualLeft += current.offsetLeft + parseFloat(getCSS(current,'border-left-width'));current = current.offsetParent;}return actualLeft + 'px'; } function getElementTop(element){var actualTop = element.offsetTop;var current = element.offsetParent;while(current != null){actualTop += current.offsetTop + parseFloat(getCSS(current,'border-top-width'));current = current.offsetParent;}return actualTop + 'px'; }
<div style="padding: 20px;border:1px solid black;position:absolute;"><div id="test" style="width:100px; height:100px; margin:10px;"></div> </div> <script> //其他浏览器返回31(10+20+1),而IE7-浏览器返回21((20和10的较大值)+1) console.log(getElementTop(test)); //所有浏览器返回31(10+20+1) console.log(getElementLeft(test)); </script>
注意事项
【1】所有偏移量属性都是只读的
<div id="test" style="width:100px; height:100px; margin:10px;"></div> <script> console.log(test.offsetWidth);//100 //IE8-浏览器会报错,其他浏览器则静默失败 test.offsetWidth = 10; console.log(test.offsetWidth);//100 </script>
【2】如果给元素设置了display:none,则它的偏移量属性都为0
<div id="test" style="width:100px; height:100px; margin:10px;display:none"></div> <script> console.log(test.offsetWidth);//0 console.log(test.offsetTop);//0 </script>
【3】每次访问偏移量属性都需要重新计算
<div id="test" style="width:100px; height:100px; margin:10px;"></div> <script> console.time("time"); for(var i = 0; i < 100000; i++){var a = test.offsetWidth; } console.timeEnd('time');//65.129ms </script>
<div id="test" style="width:100px; height:100px; margin:10px;"></div> <script> console.time("time"); var a = test.offsetWidth; for(var i = 0; i < 100000; i++){var b = a; } console.timeEnd('time');//1.428ms </script>
由上面代码对比可知,重复访问偏移量属性需要耗费大量的性能,所以要尽量避免重复访问这些属性。如果需要重复访问,则把它们的值保存在变量中,以提高性能。
强烈推荐!好文就要分享。。感谢原作者,让我重新认识了一次偏移量,谢谢!!!
javascript好文---深入理解定位父级offsetParent及偏移大小相关推荐
- 深入理解定位父级offsetParent及偏移大小
偏移量(offset dimension)是javascript中的一个重要的概念.涉及到偏移量的主要是offsetLeft.offsetTop.offsetHeight.offsetWidth这四个 ...
- javascript中定位父级offsetParent 及偏移大小
偏移量(offset dimension)是javascript中一个重要的概念.javascript中涉及到偏移的有offsetWidth.offsetHeight.offsetLeft.offse ...
- offset家族/`offsetParent`-定位父级/真实宽高:offsetWidth,offsetHeight/offsetLeft和offsetTop
01-offset家族.真实宽高:offsetWidth,offsetHeight.-真实偏移:margin和定位的偏移组合:offsetLeft和offsetTop <style>.bo ...
- CSS文档流与块级元素和内联元素
文档流 将窗体自上而下分成一行行, 并在每行中按从左至右的顺序排放元素,即为文档流. 每个非浮动块级元素都独占一行, 浮动元素则按规定浮在行的一端. 若当前行容不下, 则另起新行再浮动. 内联元素也不 ...
- width:100%与绝对定位同时存在,偏移出父级容器
当父级容器内的子元素width设为100%,而子元素又有绝对定位时,子元素伸展超出父级容器,像下面 出现这种情况的原因,width:100%,这个百分之百是相对其定位父级而言的,其定位父级有多宽,这个 ...
- 浮动属性以及清除浮动,防止父级边框塌陷的方法
1.浮动属性 left 元素向左浮动 right 元素向右浮动 none 默认值,元素不浮动 浮动就是制定一个元素沿容器的左侧或右侧位置,允许文本元素和内联元素环绕它.该元素从网页的正 ...
- CSS-实现不同尺寸大小图片自适应父级DIV
介绍:有时我们放置图片时,因为父级元素固定了大小导致图片比例失调或者是图片被裁剪,体验非常不好.下面介绍一个简单的方法(初学者,欢迎大家提出建议) HTML: <div class=" ...
- 关于DOM基础:DOM子节点:childNodes、父节点:parentNode以及相对父级元素进行定位的offsetParent
DOM基础: 子节点:chrldNodes 父节点:parentNode 节点类型:nodetype offsetParent 基本概念 子节点:通俗的说就算一个父元素下面包着一个子元素.相当于一种& ...
- 子级绝对定位,父级相对定位的由来 --- CSS定位
CSS定位:将盒子定在某一个位置,所以定位也是在摆放盒子, 按照定位的方式移动盒子. 定位 = 定位模式 + 边偏移 . 定位模式用于指定一个元素在文档中的定位方式.边偏移则决定了该元素的最终位置. ...
最新文章
- 基于EEG的脑机接口中的安全性问题
- IBASE archive pre-processing report RIBARCHV
- php 获取浏览器时区,获取用户时区
- table固定表头滚动
- [Vue.js] 深入 -- 案例 - 购物车
- Android Studio(7)---从模板添加代码
- 简说 Python 生态系统的 14 年演变
- rgb颜色查询工具_《我的眼睛–图灵识别》第三章:基础:颜色识别
- 使用localStorage存储表单数据
- 关于《趣谈网络协议》的读书笔记
- visio软件接口流程图_Microsoft Office Visio绘制系统框图以及流程图的操作步骤
- VM ESXI安装英伟达显卡驱动
- 启发式搜索求解八数码问题(Java实现,八数码小项目已开源)
- Boom 3D环绕音效软件免费安装使用教程
- 京东开源组件库NutUI 3.1 正式发布:开启多端开发之路
- 关于Mysql插入繁体字等特殊字符显示异常及查询异常
- Web 3D渲染引擎HOOPS Communicator动画编辑器的使用 | HOOPS教程
- Linux操作系统——切换到root用户及其他用户
- 23电工杯数学建模B题
- oracle substr clob,sql – 在CLOB上的SUBSTR的性能
热门文章
- java实现抽奖游戏_Java实现游戏抽奖算法
- python 零代码快速开发平台_现在低代码开发平台和零代码平台区别是什么?
- sql的子查询超级慢-子查询酿的祸
- 数据库的垂直切分和水平切分
- .net动态控件的使用(listview ,treeview,tabControl)
- python调用手机蓝牙_米家生态出品,易锁宝蓝牙U型锁,让开锁更灵活
- c语言安卓贪吃蛇代码下载,C语言贪吃蛇代码
- SQL PROMPT5.3.4.1的一些设置选项
- JS中的正则表达式小小的技巧---TEST方法的使用
- oracle 的进程