详解offset
offset
offset 译为“偏移量”,是javascript很重要的一个概念。涉及到便宜量的主要有offsetLeft、offsetTop、offHeight、offsetWidth这四个属性还有一个偏移参照--定位父级offsetParent
参照图:
在理解偏移量之前,首先要理解offsetParent。从字面上来理解。应该是翻译为“偏移父级”,但并非如此,它被译为“定位父级”
以下是对offsetParent的定义:
与当前元素最近的经过定位(不是static)的父级元素。主要分为下列几种情况:
1.元素自身有fixed定位,offsetParent的结果为null
当元素自身有fixed固定定位时,我们知道固定定位的元素相对于窗口进行定位,此时没有定位父级,故offsetParent为null
注意firefox浏览器有兼容问题
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="test" style="position: fixed"></div> <script> var test=document.getElementById('test'); console.log(test.offsetParent); </script> </body> </html>
在chrome中的执行结果:
在firefox的执行结果:
2.当元素自身无fixed定位时,且父级元素都未经过定位,offParent的结果为<body>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="test"></div> <script> var test=document.getElementById('test'); console.log(test.offsetParent); </script> </body> </html>
效果如下:
3.元素自身无fixed定位,且父级元素存在经过定位的元素,offsetParent的结果为离自身元素最近的经过定位的父级元素
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="box1" style="position: absolute;"> <div id="box2" style="position: absolute;"> <div id="test"></div> </div> </div> <script> var test=document.getElementById('test'); console.log(test.offsetParent); </script> </body> </html>
效果如下:
偏移量
偏移量共包括offsetTop、offsetLeft、offsetWidth、offsetHeight这四个属性
offsetWidth
offsetWidth表示元素在水平方向上占用的空间大小(包括边框和padding) 无单位(以px计)
offsetWidth = border-left-width + padding-left + width + padding-right + border-right-width;
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #test{ border: 2px solid #000; width: 200px; height: 200px; padding: 10px; margin: 10px; } </style> </head> <body> <div id="box1" style="position: absolute;"> <div id="box2" style="position: absolute;"> <div id="test"></div> </div> </div> <script> var test=document.getElementById('test'); console.log(test.offsetWidth); </script> </body> </html>
输出为:
offsetHeight
offsetHeight表示元素在垂直方向上占用的空间大小(包括边框和padding),无单位(以px计)
offsetHeight = border-top-width + padding-top + height + padding-bottom + border-bottom-width
[注意]如果存在垂直滚动条,offsetWidth也包括垂直滚动条的宽度;如果存在水平滚动条,offsetHeight也包括水平滚动条的高度
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <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高度为剩下的83px if(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> </body> </html>
chrome显示如下:
offsetTop
offsetTop表示元素的上外边框至offsetParent元素的上内边框之间的像素距离
offsetLeft
offsetLeft表示元素的左外边框至offsetParent元素的左内边框之间的像素距离
注意事项:
【1】所有偏移量属性都是只读的
【2】如果给元素设置了display:none,则它的偏移量属性都为0
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="test" style="width:100px; height:100px; padding:10px; margin:10px; display: none;"></div> <script> console.log(test.offsetWidth,test.offsetTop); </script> </body> </html>
chrome显示如下:
【3】每次访问偏移量属性都需要重新计算
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="test" style="width:100px; height:100px; padding:10px; margin:10px; display: none;"></div> <script> console.time("time"); for(var i = 0; i < 100000; i++){ var a = test.offsetWidth; } console.timeEnd('time');//106.701ms </script> </body> </html>
chrome显示如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> </head> <body> <div id="test" style="width:100px; height:100px; padding:10px; margin:10px; display: none;"></div> <script> console.time("time"); var a = test.offsetWidth; for(var i = 0; i < 100000; i++){ var b = a; } console.timeEnd('time');//6.274ms </script> </body> </html>
chrome显示如下:
由上面代码对比可知,重复访问偏移量属性需要耗费大量的性能,所以要尽量避免重复访问这些属性。如果需要重复访问,则把它们的值保存在变量中,以提高性能
OK offset讲解暂告一段落!