offsetLeft和offsetTop除了一个是水平方向一个是垂直方向,其他都一样,我的这里以offsetTop为例说明。
先看看官方定义:
offsetTop
返回当前元素的上边界到它的包含元素的上边界的偏移量,以像素为单位。
我认为它这里的“包含元素”严格来说指的是该元素的offsetParent,对于offsetParent的定义各个浏览器又表现的不同,我理解为无非就两种情况:要么就是某个父级元素(一般是有定位的),要么就是根body元素(严格来说这也是第一种情况)。该话题不在本文讨论范围,这里不去细究。
今天要讨论的是 可滚动元素中子元素的offsetLeft、offsetTop。先上测试代码:
1 <!doctype> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=gb2312" /> 5 </head> 6 <body style="margin:0px;overflow:scroll;"> 7 <div style="background-color:blue;200px;height:200px;overflow:scroll;"> 8 <div style="height:60px;60px;background-color:green;border:1px solid #ccc;"></div> 9 <div style="height:60px;60px;background-color:green;border:1px solid #ccc;"></div> 10 <div style="height:60px;60px;background-color:black;border:1px solid #ccc;"></div> 11 <div style="height:60px;60px;background-color:green;border:1px solid #ccc;"></div> 12 <div style="height:60px;60px;background-color:green;border:1px solid #ccc;"></div> 13 <div style="height:60px;60px;background-color:green;border:1px solid #ccc;"></div> 14 <div style="height:60px;60px;background-color:green;border:1px solid #ccc;"></div> 15 </div> 16 <script> 17 var divs = document.getElementsByTagName('div'); 18 for(var i=0;i<divs.length;i++){ 19 divs[i].onclick=function(e){ 20 e = e || window.event; 21 alert(this.offsetTop+'==='+this.offsetParent); 22 if(e.stopPropagation){ 23 e.stopPropagation(); 24 }else{ 25 e.cancelBubble = true; 26 } 27 }; 28 } 29 </script> 30 </body> 31 </html>
测试例子中有一个200x200的大div,里面包含了几个60x60的小div。点击任一一个div都会弹出它的offsetTop和offsetParent,在没有拉动大div滚动条的情况下点击黑色小div的结果如图:
从图中能看出小黑的offsetTop=124,offsetParent为body元素。人工计算一下:小黑上面有2个60x60且边框为1的小div,这样的话60+60+1+1+1+1=124,没有任何问题。
好的,接下来,往下拉动大div的滚动条,再点击小黑,在我的预期中,这次弹出的offsetTop肯定比124要小,因为小黑的上边距离body的上边距‘近’了一些,但事实是这次的结果跟之前的结果一模一样,小黑的offsetTop还是124。这是怎么回事呢?难道一个元素到body的垂直偏移值里还包含该元素父级的scrollTop?是我哪里理解的有问题吗?求大神赐教。