Introduction
The "scroll-to-top" feature is an excellent addition to any website that forces visitors to scroll a long distance before reaching the bottom of the page, since it becomes quite annoying to return back to the top.
By extension, scrolling to the bottom or any particular point or section allows you to navigate a user in a seamless experience for Single-Page Applications (SPAs).
In this hands-on guide, we will learn how to make a React button that allows users to scroll to the top, bottom or any section with React. We'll utilize React hooks and make this a reusable component. At the conclusion of this article, we'll look at how to do it with the
react-scroll-to-top
library.
Note: The source code is available in our GitHub repository, and to see a live demo of the application, visit this Vercel App.
Using React and React Hooks
For simple functionality like this, you can easily code a solution from scratch, rather than installing a library. Creating functionality like this from scratch allows for more customization and an appreciation for what libraries abstract away!
Getting Started
We'll be making a separate component, producing a reusable piece of code that can be spread out between your projects. We'll additionally be using an arrow icon from react-icons
for this guide, though, any icon that works for you will work just as well.
Installing react-icons
To use react-icons
, you have to install the module. You can install react-icons
with:
$ npm i react-icons
Scroll to Top in React
Let's import the library and the icon itself, and set them up as a component:
import React from 'react';
import { FaAngleUp } from 'react-icons/fa';
import './index.css';
const ScrollToTop = () => {
return (
<div className="top-to-btm">
<FaAngleUp className="icon-position icon-style" />
</div>
);
};
export default ScrollToTop;
Let's also apply some style to the icon and add a movement animation in index.css
:
.top-to-btm{
position: relative;
}
.icon-position{
position: fixed;
bottom: 40px;
right: 25px;
z-index: 20;
}
.icon-style{
background-color: #551B54;
border: 2px solid #fff;
border-radius: 50%;
height: 50px;
width: 50px;
color: #fff;
cursor: pointer;
animation: movebtn 3s ease-in-out infinite;
transition: all .5s ease-in-out;
}
.icon-style:hover{
animation: none;
background: #fff;
color: #551B54;
border: 2px solid #551B54;
}
@keyframes movebtn {
0%{
transform: translateY(0px);
}
25%{
transform: translateY(20px);
}
50%{
transform: translateY(0px);
}
75%{
transform: translateY(-20px);
}
100%{
transform: translateY(0px);
}
}
Great! Now we can implement the logic that takes the user back up to the top of the page.
Implementing the Logic
We'll be using the useState()
and useEffect()
hooks to allow us to develop the functionality easily and quickly.
import React, { useState, useEffect } from 'react';
The next step is to create a state
and set it to false
by default; this state will control the visibility of the "scroll-to-top" button, since we only want the button to appear after the user has scrolled down a bit and to vanish after the user has scrolled all the way to the top:
const [showTopBtn, setShowTopBtn] = useState(false);
At this point, we'll utilize the useEffect()
hook to build the logic that determines when we want the button to appear and when we want it to disappear.
Note: The Effect Hook is active by default after the initial render and each time the state is updated. It is used to conduct an effect whenever the state changes, as the name implies.
Let's set the state to true
after the user has scrolled down by 400 pixels:
useEffect(() => {
window.addEventListener('scroll', () => {
if (window.scrollY > 400) {
setShowTopBtn(true);
} else {
setShowTopBtn(false);
}
});
}, []);
We added an EventListener
to the window
to listen for a scroll and then run a function when the conditional within the listener returns true
. If the vertical scroll position is more than 400
(as determined by you), the function sets the showTopBtn
state to true
; otherwise, it sets it to false
. Remember that this will constantly run when you scroll through the webpage, and will thus update the button to stop showing when someone's scrolled back up to the top of the page.
The final functionality we'll want to implement is handling the click
event! Once the user clicks on the button, we'll want to scroll them back to the top. Thankfully - the window
object has a dedicated scrollTo()
method exactly for this! Let's wrap it around with a function we'll call when a user clicks the button:
const goToTop = () => {
window.scrollTo({
top: 0,
behavior: 'smooth',
});
};
Note: window.scrollTo()
also accepts a behavior
parameter which is used to specify whether the scrolling should be animated smoothly (smooth
), or happen instantly in a single jump (auto
, the default value).
Finally, let's add an onclick()
listener to the button in our markup, hooking it up to the goToTop()
method:
import React, { useState, useEffect } from "react";
import { FaAngleUp } from "react-icons/fa";
import "./index.css";
const ScrollToTop = () => {
const [showTopBtn, setShowTopBtn] = useState(false);
useEffect(() => {
window.addEventListener("scroll", () => {
if (window.scrollY > 400) {
setShowTopBtn(true);
} else {
setShowTopBtn(false);
}
});
}, []);
const goToTop = () => {
window.scrollTo({
top: 0,
behavior: "smooth",
});
};
return (
<div className="top-to-btm">
{" "}
{showTopBtn && (
<FaAngleUp
className="icon-position icon-style"
onClick={goToTop}
/>
)}{" "}
</div>
);
};
export default ScrollToTop;
That's it! The component can now be imported into a new page and used. In the App.js
file, let's import it:
import ScrollToTop from './ScrollToTop';
function App() {
return (
<div className="App">
<ScrollToTop />
<div className="section section1"></div>
<div className="section section2"></div>
<div className="section section3"></div>
<div className="section section4"></div>
<div className="section section5"></div>
</div>
);
}
export default App;
Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!
Note: For styling this page, refer to our GitHub repository..
Using the react-scroll-to-top Library
The react-scroll-to-top
library is a lightweight, customizable button component that scrolls to the top of the page when clicked. This component is analogous to our own, but you don't have to code it up yourself.
Naturally, it only appears once you've scrolled down enough that it makes sense for it to appear.
Installing react-scroll-to-top
Run this command in your terminal:
$ npm i react-scroll-to-top
Scroll to Top with react-scroll-to-top
To use the component, we import react-scroll-to-top
and use it as we've used our own:
Import and then include <ScrollToTop />
anywhere in your render/return function:
import ScrollToTop from "react-scroll-to-top";
function App() {
return (
<div className="App">
<ScrollToTop />
<div className="section section1"></div>
<div className="section section2"></div>
<div className="section section3"></div>
<div className="section section4"></div>
<div className="section section5"></div>
</div>
);
}
export default App;
The library is customizable as well! There's a fair bit of props you can tweak for different effects.
This has so many props, and they are all listed below with their description and the type of data they take in:
Prop | Type | Description | Default |
---|---|---|---|
smooth | boolean | Whether to use smooth scrolling* | false |
top | number | Height after page scroll to be visible | 20 |
color | string | The SVG icon fill color | "black" |
svgPath | string | The SVG icon path d attribute | An arrow path |
width | string | The SVG icon width | "28" |
height | string | The SVG icon height | "28" |
viewBox | string | The SVG icon viewBox attribute | "0 0 256 256" |
component | any | Component to override SVG icon. See examples | |
style | Object | Object to add/override styling | |
className | string | Classname to completely override styling |
Scroll to Bottom
The scroll-to-bottom feature in React works similarly to the scroll-to-top - we define a function, that on a button press, scrolls the user to a set point. This time, the point won't be the top - it'll be the bottom:
const scrollToBottom = () => {
window.scrollTo({
top: document.documentElement.scrollHeight,
behavior: 'smooth',
});
};
We set the top
property to the height of the entire page, as procured from the document
. This will ensure that we get scrolled down to the pixel-height below the entire page - or rather, to the bottom of the page.
The next step would be to include the onclick()
method in our markup for the button:
<div className="link btn" onClick={scrollToBottom}>
Scroll to bottom <MdArrowDropDownCircle />
</div>
Scroll To a Particular Section with React
Scrolling to a certain section is really popular with single-page websites, because instead of routing a user to a different page for common pages such as "About Us" and "Contact" - you can just scroll them down to the relevant section on that page. This is a popular approach when telling stories with pages, where a user is expected to scroll down anyway, but can skip to a certain section as well.
Again - this is essentially what we've been doing. This time though, we'll scroll to a given element.
Implementing the Logic
We will use the useRef()
hook - it is a built-in React hook that accepts one argument as its initial value and returns a reference. The reference has an interesting and useful property called current. The useRef()
hook is similar to Vanilla JavaScript's getElementById()
.
The first step is to import useRef()
and then create a ref (reference) to the part we want to scroll to:
import { useRef } from react;
const aboutSection = useRef(null);
The next step would be to add the ref
we declared to the section we wish to scroll to:
<div className="section section2" ref={aboutSection}>
<h2>About Us</h2>
</div>
Now, we scroll to the current reference, and offset it to the top, so as to put the top of the element at the top of the screen rather than on the bottom of it:
const scrollDown = () => {
window.scrollTo({
top: aboutSection.current.offsetTop,
behavior: 'smooth',
});
};
At this point, we have successfully implemented all the logic necessary to assist us in scrolling to a specified region of our homepage using react. Next, we'll add the onclick()
method to the button in our markup:
<li className="link" onClick={scrollDown}>
About Us
</li>
Making our Code Reusable
Nav bars typically have several links leading to several sections. Repeated actions call for generalization between instances! We can make the logic reusable this way:
const scrollDown = (ref) => {
window.scrollTo({
top: ref.current.offsetTop,
behavior: 'smooth',
});
};
In the code above, we are passing the ref
's value from the function that is being triggered in the individual's button.
The navigation bar on your page could look something along the lines of:
<div className="section section1">
<div className="link btn">
Scroll to bottom <MdArrowDropDownCircle />
</div>
<ul className="nav-links">
<li className="link" onClick={() => scrollDown(aboutSection)}>
About Us
</li>
<li className="link" onClick={() => scrollDown(servcesSection)}>
Services
</li>
<li className="link" onClick={() => scrollDown(contactSection)}>
Contact
</li>
</ul>
</div>
<div className="section section2" ref={aboutSection}>
<h2>About Us</h2>
</div>
<div className="section section3" ref={servcesSection}>
<h2>Services</h2>
</div>
<div className="section section4" ref={contactSection}>
<h2>Contact</h2>
</div>
Conclusion
In this guide, we have learned how to create a reusable component, from scratch, to perform the scroll-to-top operation easily. This component is easily transferable between projects! Just transfer the associated files and import it into a new page. Finally - we've taken a look at a popular library that takes care of this for us, as well as the props associated with customizing it.
The live demo for the application can be found here.