在第一个演示中,我使用jquery 2.1.1
并在Chrome中获得a
标记22
的偏移顶部,并且在滚动时保持相同,
但是当我在滚动时使用jquery 3.1.1
偏移更改时。
使用jquery 2.1.1
console.log($('a').offset().top);
$(window).scroll(function() {
console.log($('a').offset().top);
})

body {
height: 1200px;
}
a {
font-size: 0;
}

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a href="#">hidden anchor</a>
&#13;
使用jquery 3.1.1
console.log($('a').offset().top);
$(window).scroll(function() {
console.log($('a').offset().top);
})
&#13;
body {
height: 1200px;
}
a {
font-size: 0;
display: inline-block;
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<a href="#">hidden anchor</a>
&#13;
为什么会这样。
答案 0 :(得分:2)
jQuery 2具有正确的行为; offset()
与文档相关,因此滚动位置不应更改它。
请注意这里强调的位:
使用.offset()方法时,jQuery集合中的第一项必须是具有DOM getBoundingClientRect()方法的DOM元素。 (jQuery 3.0支持的所有浏览器都有此API。)任何其他输入都可能导致jQuery抛出错误。 另请注意,该元素必须可见且当前位于文档中(即未断开连接)。 https://jquery.com/upgrade-guide/3.0/#offset
当元素可见时,你在jQuery 3中得到了正确的行为(offset()
无论滚动位置如何都保持不变)但是当使用font-size:0
隐藏元素时,offset()
错误地返回一个视口相对值(据我所知,它通过隐藏元素的视口相对getBoundingClientRect()
值。我不知道为什么会这样做,但数字匹配)。
console.log($('a.visible').offset().top);
console.log($('a.visible')[0].getBoundingClientRect();
console.log($('a.hidden').offset().top);
console.log($('a.hidden')[0].getBoundingClientRect();
$(window).scroll(function() {
console.log($('a.visible').offset().top);
console.log($('a.visible')[0].getBoundingClientRect();
console.log($('a.hidden').offset().top);
console.log($('a.hidden')[0].getBoundingClientRect();
})
body {
height: 1200px;
}
a {
display: inline-block;
}
a.hidden {
font-size: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<a class="visible" href="#">Not-hidden anchor</a>
<a class="hidden" href="#">hidden anchor</a>
最好的解决方法似乎是不尝试测试隐藏元素的位置;使用一些带有真实文档位置的容器元素。
答案 1 :(得分:1)
正如许多人所指出的那样,这是由于offset
使用隐藏元素的方式发生了变化。我已经挖掘了代码,并且遇到了负责该行为的代码片段:
rect = elem.getBoundingClientRect();
// Make sure element is not hidden (display: none)
if ( rect.width || rect.height ) { //this line is responsible
doc = elem.ownerDocument;
win = getWindow( doc );
docElem = doc.documentElement;
return {
top: rect.top + win.pageYOffset - docElem.clientTop,
left: rect.left + win.pageXOffset - docElem.clientLeft
};
}
// Return zeros for disconnected and hidden elements (gh-2310)
return rect;
相关的行是if (rect.width || rect.height)
,这意味着,如果元素没有高度或宽度,它会跳过该部分并返回相对位置。
但是,它似乎已经fixed in the current code,所以它应该再次适用于较新的版本。现在,jQuery不会检查getBoundingClientRect()
的宽度或高度,而是检查getClientRects()
的结果。
if ( !elem.getClientRects().length ) {
return { top: 0, left: 0 };
}
当文本隐藏font-size:0
时,getClientRects()
返回一个包含一些值的数组,而真正隐藏的元素(display:none
)的结果返回一个空数组,因此更新条件将适用于“软”(?) - 隐藏元素。
console.log(document.getElementById('hidden').getClientRects());
console.log(document.getElementById('removed').getClientRects());
#hidden{
font-size:0;
}
#removed{
display:none;
}
<div id="hidden">I'm hidden.</div>
<div id="removed">I'm display:none</div>