收缩 sticky sticky header 导致 Blink/Webkit 在某些滚动位置闪烁

Shrinking sticky sticky header causes flicker in Blink/Webkit at certain scroll positions

我有一个粘性 header,它在卡住时利用 IntersectionObserver 获得 class,然后隐藏一些元素并减小徽标的大小。当然,当 header 的高度缩小时,滚动高度也会缩小,因此如果向下滚动 刚好 缩小 header,它就会缩小,然后意识到它不再卡住所以增长,而是导致它再次收缩,所以它增长,等等无限循环。这在 Chrome 中似乎是最令人震惊的,但我已经看到它也发生在 Firefox 中(尽管 Firefox 似乎认识到正在发生的事情并自行解决)。

我已经尝试了很多东西,包括 setTimeout() 在 class 被删除时延迟,在 header 收缩时添加等价的 margin-bottom,显示height 缩小 space 的隐藏元素,但似乎无法解决此问题。

我知道我之前也在其他网站上看到过这种情况,我怀疑这只是缩小 headers 的系统性问题,但我能做些什么来防止这种情况发生吗?我没主意了。

const OBSERVER = new IntersectionObserver(
    ([e]) => e.target.classList.toggle("js-is-sticky", e.intersectionRatio < 1),
    {
        rootMargin: document.getElementById("wpadminbar") ? "-32px 0px 0px 0px" : "0px 0px 0px 0px",
        threshold: [1],
    }
);

OBSERVER.observe(document.querySelector(".sticky-block"));

CSS 和标记有点复杂(并且稍微不相关),所以如果需要,请参考我们的演示站点。 https://gepl.myweblinx.net/

如果需要其他任何内容,我很乐意添加。

编辑 1:我看到 this answer 建议在保持正确高度的元素周围放置一个容器,但这不适用于 position: sticky;,因为 position: sticky; 仅适用于最近的容器(除非有人知道如何解决这个问题?)

编辑 2:我对第一次编辑的答案想得太多了

好吧,这是一个非常明显的解决方案...感谢 this answer,我能够弄清楚如果我只是在粘性元素上设置一个固定的高度,但让该元素的内容缩小,问题就解决了。

本质上:

<div class="sticky-block" style="height:140px;">
    <div class="header-block">
        ...
    </div>
    <div class="navigation-block">
        ...
    </div>
</div>

在我的情况下,这些解决方案不起作用,Android 上的 Chrome 仍然存在闪烁问题。我的解决方案是固定我的页眉位置,并在其后面放置一个虚拟 div,将其调整为与页眉相同的高度。

<html>

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    <style>
        :root {
            --lightGrey: #bbbbbb;
        }

        body {
            margin: 0;
            width: 100%;
            height: 500%;
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            grid-template-rows: repeat(9, auto);
            grid-column-gap: 0px;
            grid-row-gap: 0px;
        }

        header {
            width: 100%;
            grid-area: 1 / 1 / 1 / 4;
            position: fixed;
            top: 0;
            z-index: 100;
            background-color: var(--lightGrey);
        }

        .headerBackground {
            grid-area: 1 / 1 / 1 / 4;
            background-color: var(--lightGrey);
            height: fit-content;
        }
    </style>
</head>

<body>
    <header>My Header</header>
    <div class="headerBackground">Background div</div>
</body>

<script>
    // Changes the header once you have scrolled down by 100 pixels or more
    $(window).scroll(function () {
        if ($(window).scrollTop() >= 100) {
            $('header').css('height', '20vw');
            $('header').css({ 'font-size': '4vw', 'padding': '5vw' });
        } else if ($(window).scrollTop() == 0) {
            $('header').attr('style', '');
        }
    });

    // This keeps the space behind the header at the same height as the header to get around the flickering sticky 
    $(".headerBackground").css({ 'height': ($("header").height() + 'px') });
</script>

</html>