问题1:什么是offsetParent?
解答:返回的是被定位的祖先元素,如果没有被定位的元素是body元素!
问题2:发生margin重叠以后,我们怎么计算到offsetParent的距离?
注意:下面的例子都是在标准模式下测试的结果
<div style="width:200px;height:200px;margin-top:10px;" id="outer"> <div style="width:100px;margin-top:200px;height:200px;border:1px solid red;" id="div"> </div> </div>上面这种情况肯定会发生margin重叠
//offsetParent如果没有被定位的元素的情况下,如果和body发生了margin重叠,那么所有元素的offsetTop值都是相当于html而不是body元素来计算的! var outer=$('#outer')[0].offsetTop; console.log(outer); //打印200 var div=$('#div')[0].offsetTop; console.log(div); //打印200因为body的margin默认是8px,#outer元素的margin-top是10px,而#div元素的margin-top为200px,所以发生重叠以后outer,div,body元素都在html元素的基础上往下移动了200px(可以阅读 body元素和html元素之间的一些表现一文)!这时候,如果是按照body来计算的,也就是offsetParent是body元素,那么显然#outer,#div元素的offsetTop应该是0,但是结果不是这样,从上面的打印结果我们知道#outer,#div元素的offsetTop是200px,是怎么回事?
其实我也不清楚,既然下面一个例子说offsetParent是body元素,那么显然我不是相对于body来定位的啊!
我猜测:如果DOM树中没有一个元素被定位,那么这时候offsetParent虽然打印了body,但是定位是相当于与html元素的,也就是所有元素距离offsetParent的距离是距离html元素的距离!还有一点请注意:虽然offsetTop是相对html元素定位,但是浏览器打印的是body元素,所以获取body元素的offsetTop时候始终是0!
按照我上面的逻辑,在这种情况下,offsetParent是body元素,但是计算offsetParent的距离是计算到html的距离我来举一个例子:
<div style="width:100px;height:100px;" id="test"></div>如果说是按照body定位的,那么body只有默认的margin,那么offsetTop应该是0
var test=$('#test')[0]; //打印body console.log(test.offsetParent.tagName); //打印8px console.log(test.offsetTop);但是结果是不对的,他的offsetTop是8px,所以我猜测 offsetTop在没有定位父元素时候,其距离的计算是相对于html来说的!
我们首先来看一看每一个元素的offsetParent是谁?
var outer=$('#outer')[0]; var div=$('#div')[0]; var body=$('body')[0]; console.log(outer.offsetParent.tagName); //打印body console.log(div.offsetParent.tagName); //打印body console.log(body.offsetParent); //打印null
很显然,对于div元素,outer元素其offsetParent是body元素,所以,很显然body元素的offsetParent是不存在的为null!
问题3:如果没有父元素被定位,那么offsetTop获取的就是到html的距离,那么这有什么用?
<div style="width:100px;height:100px;" id="test1"></div> <div style="width:100px;height:100px;margin-top:100px;" id="test2"></div>我们也给元素设定一个css样式
html { background-color:blue; } body { margin-top:10px; }我们可以通过这个特性获取两个兄弟元素之间的距离
var test1=$('#test1')[0]; var test2=$('#test2')[0]; console.log(test2.offsetTop-test1.offsetTop); //打印200,就是#test1的height加上#test2的marginTop!这也就是告诉我们,不管元素的父元素的css多么复杂,我都可以用这种方法获取到子元素的兄弟节点之间的距离,同时更加有用的是,可以通过offsetTop获取到元素距离最顶部的距离,也就是html的距离(这个和html本身的移动即marginTop值是没有关系的)!