React:iOS Safari 中的粘性标题闪烁

时间:2021-05-14 03:15:13

标签: javascript css reactjs sticky onscroll

我在 React 中使用以下代码来设置粘性标题。我已经包含了 topsetTop 来演示导致问题的原因。我不包括标题的 CSS,因为 top 的值表明问题不在于 CSS(如有必要,我可以更新问题)。

const BodyHeader = props => {
    const [top,setTop] = useState(0);
    const ref = useRef(null);
    const handleScroll = () => {
        if (!ref.current) return;
        setTop(ref.current.getBoundingClientRect().top);
        const classList = ref.current.classList;
        if (ref.current.getBoundingClientRect().top < 1) {
            if (!classList.contains("sticky-header")) {
                classList.add("sticky-header");
            }
        } else {
            classList.remove("sticky-header");
        }
    };

    useEffect(() => {
        window.addEventListener('scroll', handleScroll);

        return () => {
            window.removeEventListener('scroll', () => handleScroll);
        };
    }, []);

    return <div id="body-header" ref={ref}>
        <div id="header-inner">
            <div style={{color: "red"}}>{top}</div>*/}
        </div>
    </div>
}

我在 iOS Safari 中看到的是 top 的值到处跳跃。我最初有 ref.current.getBoundingClientRect().top <= 0,但是,在添加 divtop 后,我看到滚动时该值跳转到小数值。将其更改为 < 1 可以消除大部分问题,但是,如果我快速滚动并松开拇指并让它自由滚动而不让我的拇指接触,它会再次开始闪烁。

当我滚动回页面顶部时尤其糟糕。这就像 Safari 正在计算滚动停止后 div 的位置(而不是当前位置)。在 macOS 上的 Chrome 或 Safari 中不会出现此问题。

我也在 body 上使用这个 CSS:

-webkit-overflow-scrolling: touch;

是否需要在 JS 或其他 CSS 中更改影响滚动的内容?我改变的不仅仅是标题的位置,所以我需要添加类而不是仅仅使用 position: sticky

我已经看到许多关于闪烁标题的类似问题,但我还没有看到这个特定问题在哪里得到解决。

1 个答案:

答案 0 :(得分:0)

我找到了一个非常简单的解决方案。我只需要添加一个包装 div 作为参考,而不是我想要粘贴的 div:

return <div className="body-header-wrapper" ref={ref}>
    <div id="body-header">
        <div id="header-inner">
        </div>
    </div>
</div>

body-header-wrapper 是新的 div,ref={ref} 已移到那里。这个想法是,即使它的子 div,body-header,由于粘性定位,它从顶部的绝对位置仍然不稳定(我通过显示 top 的值再次检查,因为我之前做过),body-header-wrapper 不会被重新定位,因此闪烁不再发生。