几个Demo带你理清offsetLeft和offsetTop
前言
最近做项目或者前面的视频播放器,会很经常接触到offsetLeft和offsetTop,用的时候还是有点迷迷糊糊,所以今天做几个demo彻底理清下这两个到底根据的是谁来计算距离
一、offsetLeft和offsetTop是什么?
首先来看MDN是怎么来介绍的:HTMLElement.offsetLeft和HTMLElement.offsetTop是一个只读属性,返回当前元素左上角相对于HTMLElement.offsetParent节点的左内边界偏移的像素值。
这里又牵扯到一个新概念:offsetParent,这又是什么呢?
二、offsetParent是什么?
MDN文档搜索得知HTMLElement.offsetParent 是一个只读属性,返回一个指向最近的(指包含层级上的最近)包含该元素的定位元素或者最近的 table,td,th,body元素。当元素的 style.display 设置为 "none" 时,offsetParent 返回 null。offsetParent 很有用,因为 offsetTop 和 offsetLeft都是相对于其内边距边界的。
三、具体demo分析
对以下元素结构进行分析
1 <div class="wrap">红色 2 <div class="wrap2">黄色 3 <div class="inner">粉色</div> 4 </div> 5 </div>
对offsetLeft和offsetTop进行输出打印
var inner=document.querySelector('.inner') console.log('offsetLeft:'+inner.offsetLeft,'offsetTop:'+inner.offsetTop)
效果图:
1.本身定位不为fixed,父级有定位
1 .wrap{position:relative;left: 20px; background-color: red;} 2 .wrap2{position:relative;background-color: yellow;} 3 .inner{background-color: pink;}
输出:
1 .wrap{position:relative;left: 20px; background-color: red;} 2 .wrap2{background-color: yellow;} 3 .inner{background-color: pink;}
输出:
以上可以得出什么呢?粉色框因为没开定位,所以他的offsetTop是根据最近的开启定位的父元素的内边框来计算距离(字体占了21)。
1 .wrap{position:relative;left: 20px; background-color: red;} 2 .wrap2{position:relative;background-color: yellow;} 3 .inner{position:absolute;background-color: pink;}
输出为
这里粉色框开了定位且不为fiexd,但是他的offsetTop还是根据最近的开启定位的父元素的内边框来计算距离(字体占了21)。
所以我们总结为只要自身不为fiexd定位,offsetTop和offsetLeft就根据最近的开启定位的父元素的内边框来计算距离,这是因为offsetParent在这种情况下指向的都是最近的开启定位的父元素,这也说明了offsetTop和offsetLeft确实是根据offsetParent来计算的
2.本身定位不为fixed,父级没有定位
1 .wrap{margin: 10px 20px; background-color: red;} 2 .wrap2{background-color: yellow;} 3 .inner{background-color: pink;}//自身没开启定位
输出为:
1 .wrap{margin: 10px 20px; background-color: red;} 2 .wrap2{background-color: yellow;} 3 .inner{position:relative;background-color: pink;}//自身开启非fixed的定位
输出为:
我们可以看到这里的父元素没有开启定位元素,那这里的offsetTop和offsetLeft是根据什么呢?答案是body.让我们来算下offsetLeft如果按父元素应该是0,这里是20,其实就是因为加了20的margin-left.offsetTop如果按父元素应该是21或者42,这里是52,其实就是因为最外面的父元素加了10的margin-left.就等于粉色框距离body的长度。所以总结为只要自身不为fiexd定位,offsetTop和offsetLeft就根据最近的开启定位的父元素的内边框来计算距离,如果父元素都没有开启定位,那就按照body作为标准来计算。
3.本身定位为fixed,浏览器不为火狐(这边只给出在chrome下的结果,其他类似)
1 .wrap{margin: 10px 20px; background-color: red;} 2 .wrap2{background-color: yellow;} 3 .inner{position:fixed;background-color: pink;}
chrome输出为:
1 .wrap{margin: 10px 20px; background-color: red;} 2 .wrap2{position:relative;background-color: yellow;} 3 .inner{position:fixed;background-color: pink;}
chrome输出依然为:
我们可以得到,当自身定位为fixed,且浏览器不为火狐,不管父元素有没有开启定位,他的offsetParent都是指向null,但是他的offsetTop和offsetLeft依然是根据body来计算的
4.本身定位为fixed,浏览器是火狐
1 .wrap{margin: 10px 20px; background-color: red;} 2 .wrap2{position:relative;background-color: yellow;} 3 .inner{position:fixed;background-color: pink;}
火狐下输出为:
我们可以得到,当自身定位为fixed,且浏览器是火狐时,不管父元素有没有开启定位,他的offsetParent都是指向body,所以他的offsetTop和offsetLeft自然是根据body来计算的
四、总结
从上面多个例子我们可以知道offsetLeft和offsetTop确实是根据offsetParent来计算的,所以我们需要知道offsetParent在某个情况具体指的是啥,因为他需要考虑兼容性还有父子元素是否开启定位等复杂情况,测试情况过于冗余,下面就直接给出本文结论:
本身定位为fixed
==>offsetParent:null(不是火狐),此时offsetLeft和offsetTop是根据body来计算的
==>offsetParent:body(火狐)
本身定位不为fixed
父级没有定位
==>offsetParent: body
父级有定位
==>offsetParent:定位父级

浙公网安备 33010602011771号