Cra*_*own 7 html css css-position sticky
我注意到 Chrome 和 Safariposition: sticky对元素的处理略有不同。
具体来说,当粘性元素变得更高,并且窗口当前滚动以使粘性元素偏离其初始位置时,Chrome 将以scrollTop相同的量改变位置 - 使内容的外观保持静止,而粘性元素长在顶部。
在 Safari 中,scrollTop在这种情况下位置保持不变,内容看起来向下移动以适应粘性元素增加的高度。
我在下面创建了一个代码片段来演示浏览器在这种情况下的行为方式。上面的屏幕截图显示了该演示在每个浏览器上的表现,但您可以在这里亲自尝试。
function grow() {
const header = document.getElementById("header");
document.getElementById("header").classList.toggle("large-header");
updateScrollText();
}
function updateScrollText() {
const container = document.getElementById("container");
const scrollParent = getScrollParent(container);
document.getElementById("scrollbarpos1").innerHTML = scrollParent.scrollTop;
document.getElementById("scrollheight1").innerHTML = scrollParent.scrollHeight;
document.getElementById("containerheight1").innerHTML = container.offsetHeight;
document.getElementById("scrollbarpos2").innerHTML = scrollParent.scrollTop;
document.getElementById("scrollheight2").innerHTML = scrollParent.scrollHeight;
document.getElementById("containerheight2").innerHTML = container.offsetHeight;
}
function getScrollParent(node) {
if (node == null) {
return null;
}
if (node.scrollHeight > node.clientHeight) {
return node;
} else {
return getScrollParent(node.parentNode);
}
}
window.onscroll = updateScrollText;
window.onload = updateScrollText;Run Code Online (Sandbox Code Playgroud)
#header {
background-color: #CACACA;
position: sticky;
top: 0;
padding: 20px;
}
.large-header {
height: 100px;
}
.content {
background-color: #a2a6c4;
height: 1500px;
}
.shift-down {
margin-top: 50px;
}Run Code Online (Sandbox Code Playgroud)
<div id="container">
<div id="header">
<button type="button" onclick="grow()">Grow/Shrink</button>
</div>
<div class="content">
<br>
Scrollbar position: <span id="scrollbarpos1">0</span>
<br>
Scroll height: <span id="scrollheight1">0</span>
<br>
Container height: <span id="containerheight1">0</span>
<br>
<br>
Voluptatibus omnis perspiciatis consequatur magni error exercitationem saepe qui. Ipsa sint non labore voluptates. Asperiores aut non ullam aut sit omnis ducimus in. Aut enim nihil unde ad expedita. Ratione necessitatibus quasi dolorem sunt aperiam nobis ducimus.
Sequi quasi maiores eos aut non. Ipsam delectus sit facilis aut. Dolor facilis eum dignissimos. Vero reiciendis odio quis blanditiis.
Error nesciunt rem facilis. Neque labore et qui sequi eos corrupti dolorem. Reprehenderit qui voluptatem et neque ducimus ipsum similique fugit. Ea sint alias qui laborum nesciunt. Nihil ex repellendus odit sint unde fuga.
A eum nulla ut cumque necessitatibus culpa exercitationem unde. Corrupti sit minima eveniet et aut possimus sapiente. Est accusantium aut ut numquam illo.
Praesentium fugit pariatur eum ad velit distinctio culpa id. Quia voluptatum dignissimos consequatur. Eaque nihil voluptas in voluptas voluptas eius voluptas.
<br>
<br>
<div class="shift-down">
Scrollbar position: <span id="scrollbarpos2">0</span>
<br>
Scroll height: <span id="scrollheight2">0</span>
<br>
Container height: <span id="containerheight2">0</span>
</div>
</div>
</div>Run Code Online (Sandbox Code Playgroud)
我查看了关于定位布局的 W3C 规范,但找不到任何具体定义其工作原理的内容。
所以我的问题是:
Ant*_*ber 12
为什么这两个浏览器上的行为不同?
要理解这一点,您首先需要了解粘性元素如何占用页面上的空间。当您滚动经过粘性元素时,粘性元素的渲染部分会跟随视口的顶部,但该元素在物理上仍然占用其最初放置的空间:
当您调整标题大小时,这会使浏览器处于一种奇怪的情况,因为它实际上是您已经滚动过去的元素。有两种方法可以解决这个问题。您可以像 Safari 和 Firefox 一样,始终与文档顶部保持相同的距离,或者您可以像 Chromium 一样,移动视口,使其跟随您当前正在查看的元素:
我相信 Safari 和 Firefox 都是这样做的,因为这是最简单的解决方案,而且每个浏览器一直都是这么做的。我相信 Chromium 最近改变了它的方法,因为当用户阅读带有缓慢加载广告的文章时,它具有明显的优势,这些广告在加载后会改变大小:
正如您在上面所看到的,当广告在 Safari 和 Firefox 中加载时,它会导致页面内容发生重大变化,这会让用户感到烦恼和迷失方向。如果有多个广告相继加载,这尤其糟糕。使用 Chromium 方法,可以调整视口,以便用户甚至不会注意到发生了任何事情。
我无法找到任何规范或讨论来支持我的主张,但我很确定这就是背后的原因。我不确定 Firefox 或 Safari 是否有理由不实现 Chromiums 方法,或者他们只是觉得它没有那么重要。
如果有的话,哪一个是“正确的”?
哪种解决方案最好可能是一个非常复杂且有些主观的讨论,我不会深入讨论,尽管 Chromium 方法的好处是不可否认的。
有没有办法让两个浏览器表现相同(无论哪种方式)?
当您按下Grow/Shrink按钮时,您始终可以检测滚动高度是否发生变化,然后在更改后立即将其设置回来。您也可以执行相反的操作并自行更改滚动高度,以便所有浏览器的行为都类似于 Chromium。这是一篇来自某人的旧文章,正是这样做的:
https://simonerescio.it/en/2017/03/chrome-changes-its-center-of-gravity-reference-is-not-the-document-but-视口