I’m encountering a flickering issue in my React component when implementing a fixed positioning effect on scroll. Here’s the scenario:
I have a parent <div>
that takes the minimum height of the screen (min-h-screen
) and contains three child <div>
elements, each taking the full height of the screen (h-screen
). The objective is to achieve the following behavior:
-
When the top of the parent
<div>
reaches the top of the screen, the first child should be displayed in the viewport. -
As the user scrolls, the subsequent children should come into view one after another, with the first child always at the top until the last child is reached.
-
When the bottom of the parent
<div>
reaches the bottom of the screen, the parent<div>
should move with the scroll and no longer remain fixed.
I’ve implemented this functionality using React hooks (useRef
, useState
, useEffect
) to detect the scroll position and toggle the fixed positioning accordingly. However, I’m encountering a flickering issue specifically when the bottom condition is met.
import { useEffect, useRef, useState } from "react";
export default function WhatWeDo() {
const ref = useRef<HTMLDivElement>(null);
const [isFixed, setIsFixed] = useState(false);
useEffect(() => {
const handleScroll = () => {
if (ref.current) {
const divTop = ref.current.getBoundingClientRect().top;
const divBottom = ref.current.getBoundingClientRect().bottom;
const screenHeight = window.innerHeight;
if (divTop <= 0 && divBottom >= screenHeight) {
setIsFixed(true);
} else if (divTop > 0 || divBottom < screenHeight) {
setIsFixed(false);
}
}
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return (
<div
ref={ref}
className="w-full min-h-screen flex flex-col bg-gray-50 gap-20 items-start justify-start"
>
{/* Background text */}
<div
className={`${
isFixed ? "fixed" : ""
} w-full max-h-screen h-screen flex justify-center items-center bg-pink-200 left-0 top-0`}
>
<span className="text-8xl font-bold text-black">
WHAT WE DO {isFixed ? "fixed" : "notfixed"}
</span>
</div>
<div className="w-full h-screen"></div>
<div className="w-1/2 max-h-screen h-screen flex justify-center items-center bg-blue-200 z-10">
<span className="text-8xl font-bold text-black">WHAT WE DO 1</span>
</div>
<div className="w-1/2 max-h-screen h-screen flex justify-center items-center bg-orange-200 z-10">
<span className="text-8xl font-bold text-black">WHAT WE DO 2</span>
</div>
<div className="w-full h-screen"></div>
</div>
);
}