14
Implementing a Scroll To Top feature in React
The Window object provides a few methods that allow us to programmatically scroll around a web page, such as smooth scrolling to specific sections or returning the user to the top of the page.
Recently I used this on a project to create a "return to top" button that would appear once a user has begun scrolling down the page, and when clicked would quickly return the user to the top of the page.
To begin, we first need to register the element that we want to use as the target for the scroll action. For a "return to top" this could be the heading of the page, or any other element at the top that you choose. To register these elements using React Hooks, we will need to utilize the useRef hook to register the element.
First create the marker:
const topRef = useRef(null);
Second, attach it to the desired element using its ref
attribute:
<div className="App">
<h1 ref={topRef}>Scroll To Top Example</h1>
</div>
For the button itself, we can create a new component and assign a scrollToRef
function to its click event. This function takes will accept the target ref, and use the scrollTo()
function on the window
object to scroll the window until the top of the ref
element is visible. To make this action smooth, instead of an instantaneous jump, we can optionally pass a "behavior" property:
const scrollToRef = (target) => {
window.scrollTo({
top: target.current.offsetTop,
behavior: "smooth"
});
}
In my implementation, I wanted the button to only render once the user has scrolled a pre-defined distance down the page. To achieve this, we can utilize the scrollY
property on the window
object to determine how far down the page the user has scroll. With an event listener on the scroll event for the window, we can then compare the scrollY position of the window at each scroll to determine if the button's "show" state should be true or false. Alternatively, we could make this comparison on scroll start or scroll end to improve performance, but it would change its behavior.
Since the button will be mounted/unmounted conditionally, its important to remove the scroll event listener from the window object when the button is unmounted. To do this, we can return a cleanup function using the useEffect
hook that will be invoked when the component un-mounts.
const GoToButton = ({ displayAfter, target }) => {
const [showButton, setShowButton] = useState(false);
const handleShowButton = () => {
if (!showButton && window.scrollY > displayAfter) {
setShowButton(true);
return;
}
if (!showButton && window.scrollY <= displayAfter) {
setShowButton(false);
return;
}
};
window.addEventListener("scroll", handleShowButton);
useEffect(() => {
return window.removeEventListener("scroll", handleShowButton);
});
const scrollToRef = (target) => {
window.scrollTo({
top: target.current.offsetTop,
behavior: "smooth"
});
};
if (showButton) {
return <Button onClick={() => scrollToRef(target)}>TOP</Button>;
} else {
return "";
}
};
export default GoToButton;
Similar approaches could be used to scroll down the page to different sections using a content menu and multiple section refs. The window object also has a scrollBy
method which could be used in place of scrollTo if the desired behavior was to always scroll a specific distance, such as using window.scrollBy(0, window.innerHeight)
to scroll down by one page.
The code for the demonstration of this scroll to top feature in the animation can be found on this CodeSandbox
14