作为一只前端喵,经常在学习工作中遇到关于定位的问题,踩过几次坑,特开此篇作为自己的踩坑历程小记录。
第一个坑:jQuery.position(),你为啥不听父元素的!
某天在尝试做一个滑动功能,通过元素相对于父元素的位置来确定是否触发滚动。当时想到了jQuery提供的position()
方法,看w3school提供的定义和用法——
position() 方法返回匹配元素相对于父元素的位置(偏移)。
这不就是我想要的效果吗~
piu一下写了个用position()
获取位置的打印语句,想验证一下元素在滚动时的位置变化,结果如下图。
光看着觉得没什么问题,位置果然随着滚动在变化。但细看一下突然觉得有点奇怪,我选取的两个元素是下面这样的形式:
子元素的高度大于父元素,因此会产生滚动条。但讲道理一开始没有滚动时,子元素相对于父元素的top位置应该是0啊,怎么是从99开始的呢?left也是同样的问题。再一想,我把这两个元素固定在距文档上方100px的位置,难道99是从这里出来的?那这样一来,position()
的作用倒变得像offset()
了(w3school: offset() 方法返回或设置匹配元素相对于文档的偏移(位置)),有点奇怪啊。
找了一下,发现其他人用起来好像都没有遇到过这样的问题,不过直觉告诉我是不是和父元素的某些特征有关系,直接去翻了jQuery的官方文档。
The .position() method allows us to retrieve the current position of an element relative to the offset parent. Contrast this with .offset(), which retrieves the current position relative to the document.
果不其然,官方文档的定义里写的是relative to the offset parent,问题一定出在offset parent上。不过讲真,我一时没有明白offset parent的意思,查了一下才发现指的是“定位父级”的意思。
立马把父元素改为position: relative
,重新试一下效果,一切正常啦~
最后总结一下这个问题,不是position()
方法不听父元素的,而是它只听命于定位父元素。后来经过试验,当前元素的偏移量参考为最近的定位父辈元素,若没有定位父辈元素,则参考当前窗口。
第二个坑:长得像不一定一样之jQuery.offset()与offsetLeft/offsetTop
第二个坑和第一坑类似。
因为平时练手一般都习惯用原生来写,某天在看一个用jQuery写的demo的时候,也用原生在边看边敲。教程里要获取一个元素的左上角坐标,使用了offset()
方法,我写的时候直接用offsetTop/offsetTop来替换。运行的时候发现获取到的位置总是不对。
当时获取的是一个position:absolute
的元素,设置了left:200
,断电调试发现offsetTop
也总是获取到200。查了文档发现offsetTop
返回的是the distance of the current element relative to the top of the offsetParent node。
又是offsetParent!T^T
不过反过来又查了一下jQuery.offset(),它的返回值是the current coordinates of the first element in the set of matched elements, relative to the document。
本来以为两个东东长得像就是一样的,果然不能被外表骗了。