我在 React 中使用以下代码来设置粘性标题。我已经包含了 top
和 setTop
来演示导致问题的原因。我不包括标题的 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
,但是,在添加 div
和 top
后,我看到滚动时该值跳转到小数值。将其更改为 < 1
可以消除大部分问题,但是,如果我快速滚动并松开拇指并让它自由滚动而不让我的拇指接触,它会再次开始闪烁。
当我滚动回页面顶部时尤其糟糕。这就像 Safari 正在计算滚动停止后 div 的位置(而不是当前位置)。在 macOS 上的 Chrome 或 Safari 中不会出现此问题。
我也在 body 上使用这个 CSS:
-webkit-overflow-scrolling: touch;
是否需要在 JS 或其他 CSS 中更改影响滚动的内容?我改变的不仅仅是标题的位置,所以我需要添加类而不是仅仅使用 position: sticky
。
我已经看到许多关于闪烁标题的类似问题,但我还没有看到这个特定问题在哪里得到解决。
答案 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
不会被重新定位,因此闪烁不再发生。