Add a "Back to top" button in React
One of the most common (and useful) functionalities today is to add a “back to top” button to our pages, especially when our content tends to be long.
And the truth is that it is not very difficult to achieve, with a few lines of code you can achieve something very flashy, like what I have on this blog (which I really liked the result).
So below I will leave the steps I took to add a “back to top” button in React to this blog, which although it is made with Next.js, in the end it is still React. Let's get started:
Table of contents
- Step 1: Add the button
- Step 2: Add the code for “back to top”
- Step 3: Style the button
- Step 4: Show the button when we scroll down the page
Step 1: Add the button
For practical purposes, in this tutorial I will use Tailwind CSS (since it is what I use on the blog). But I will explain the reasoning in terms of CSS so that it is easily transportable to any other system.
Step 1.1 Creating the button
The basic functionality of a back-to-top button is nothing more than an anchor on the page, which we will link in our button to make a “jump” to the top of the page. For example:
1<main id=“content”>2 […our content]3</main>4
And at the bottom of our site we add our button:
1<a href=“#main”>Back to top</a>2
In theory that's all we need, but honestly it is a bit outdated, and the jump can seem sudden to many people, so most of the time we add a little Javascript to make the jump smoother.
Let's start by creating the button in React:
Step 2: Add the code for “back to top”
To create a button in React, the first thing we need is a component that allows us
to make the jump. In this case, I will call it BackToTopButton
.
1import React from 'react';23export default function BackToTopButton() {4 return <a href='#main'>Back to top</a>;5}6
And then, in our main component, we import it and add it at the end
1import BackToTopButton from './BackToTopButton';23export default function Main() {4 return (5 <main id='main'>6 […our content]7 <BackToTopButton />8 </main>9 );10}11
That will add the button to the end of our page, now, to make the jump smoother,
what we need is to add a little Javascript, to use the scrollTo
function of Javascript.
Also, since we are using Javascript to handle the jump, it is more optimal not to use
an anchor
in the button, but to use a button
instead.
1import React from 'react';23export default function BackToTopButton() {4 // Function to make the jump when clicked.5 const handleClick = () => {6 window.scrollTo({7 top: 0,8 behavior: 'smooth', // Makes the jump smoother.9 });10 };1112 return <button onClick={handleClick}>Back to top</button>;13}14
Why don't we use an anchor
?
When we use the a
tag with an href
pointing to an id
on the page,
we are effectively creating a link to some part of our page. But
in this case, instead of a link, we are creating a user interaction.
Therefore, it is more semantic to use a button
instead of an anchor
.
Also, when using a button we don't have to worry about preventing the default
behavior of the browser, since buttons don't have a default behavior.
In other words, we don't need to add e.preventDefault()
in the event handler.
2.1 How does scrollTo
work?
The way scrollTo
works is quite simple, we simply pass it an object with the
properties top
and behavior
. The top
property is the position (in pixels)
we want to jump to, in this case 0
to go to the top of the page.
The behavior
property is what makes the jump smoother, since we are
telling it to do it smoothly
. If we don't pass this property, the jump will be
instantaneous.
We can also pass other properties like left
to make a horizontal jump, but
in this case we don't need it.
Step 3: Style the button
Now that we have our button, we need to give it a little style. In my case, I will use Tailwind CSS as I mentioned earlier, but you can use any style system you prefer.
Basically what we will do is make a circular button that contains an arrow pointing upwards. To do this, we need to add a little CSS to our component.
Tailwind uses inline CSS classes, so we don't need to import a styles file, we simply add the classes directly in the component.
Below this example I will show you how to do it with normal CSS.
1import React from 'react';23export default function BackToTopButton() {4 const handleClick = () => {5 window.scrollTo({6 top: 0,7 behavior: 'smooth',8 });9 };1011 return (12 <button13 onClick={() => {14 window.scrollTo({ top: 0, behavior: 'smooth' });15 }}16 className='fixed bottom-0 right-0 z-50 m-4 rounded-full bg-primary p-2 text-white shadow-lg ring-1 ring-secondary'17 >18 Back to top19 </button>20 );21}22
3.1 How to do it with normal CSS?
If you prefer to use normal CSS, you can do it like this:
1button {2 background-color: var(--color--primary); // Or our primary color.3 border: 1px solid var(--color--secondary); // Or our secondary color.4 border-radius: 50%;5 box-shadow: 0 0 10px rgba(0, 0, 0, 0.2); // Defined by Tailwind.6 color: white;7 inset-block-end: 0;8 inset-inline-end: 0;9 margin: 1rem; // 16px or "4" in Tailwind terms.10 padding: 0.5rem; // 8px or "2" in Tailwind terms.11 position: fixed;12 z-index: 50;13}14
Basically, what we are doing is creating a circular button with a primary background color, a secondary border, a shadow, and white text color. Also, we are positioning it in the bottom right corner of the page. And specifying that it should always stay there.
For our arrow icon, we can use an icon from Heroicons,
which is an open-source icon library, created by the Tailwind team.
In this case, we will use the arrow-up
icon:
1import React from 'react';2import { ArrowUpIcon } from '@heroicons/react/24/solid';34export default function BackToTopButton() {5 const handleClick = () => {6 window.scrollTo({7 top: 0,8 behavior: 'smooth',9 });10 };1112 return (13 <button14 onClick={() => {15 window.scrollTo({ top: 0, behavior: 'smooth' });16 }}17 className='fixed bottom-0 right-0 z-50 m-4 rounded-full bg-primary p-2 text-white shadow-lg ring-1 ring-secondary'18 >19 <ArrowUpIcon className='h-6 w-6' />2021 <span className='sr-only'>Back to top</span>22 </button>23 );24}25
This will give us a result similar to the following (try clicking it 😉):
What is sr-only
?
sr-only
is a Tailwind class that hides an element visually, but keeps it
accessible to screen readers. In this case, we are using a span
with the
text “Back to top” so that screen readers know what the button does.
Step 4: Show the button when we scroll down the page
Now we have our button on the page, however there are several adjustments we can make, for example, we don't need to add a “back to top” button if we are at the top of the page. Therefore we should only show the button when the user has scrolled down a bit, so that it makes sense.
Since we are using React, we can use the useState
hook to handle the state of
our button. For example, we can create a state called showButton
that is true
when the user has scrolled more than 100px
on the page.
To know where the user is on the page, we can use the window.scrollY
property of
Javascript, which will give us the number of pixels the user has scrolled down the
page. This together with the scroll
event, which will check every time the user
scrolls.
Finally, to make the check more efficient, we can use the useEffect
hook that
saves a reference to the scroll
event and removes it when the component is unmounted.
We always have to think about the cleaning of our components.
1import React, { useState, useEffect } from 'react';2import { ArrowUpIcon } from '@heroicons/react/24/solid';34export default function BackToTop() {5 const [showButton, setShowButton] = useState(false);67 useEffect(() => {8 // Function to show the button when the user has scrolled more than 100px.9 const toggleVisibility = () => {10 if (window.scrollY > 100) {11 setIsVisible(true);12 } else {13 setIsVisible(false);14 }15 };1617 // Add the scroll event.18 window.addEventListener('scroll', toggleVisibility);1920 // Clean the event when the component is unmounted.21 return () => {22 window.removeEventListener('scroll', toggleVisibility);23 };24 }, []);2526 const handleClick = () => {27 window.scrollTo({ top: 0, behavior: 'smooth' });28 };2930 return (31 showButton && (32 <button33 onClick={handleClick}34 className='fixed bottom-0 right-0 z-50 m-4 rounded-full bg-primary p-2 text-white shadow-lg ring-1 ring-secondary'35 >36 <ArrowUpIcon className='h-6 w-6' />3738 <span className='sr-only'>Back to top</span>39 </button>40 )41 );42}43
With this, we already have a “back to top” button that is displayed when the user
has scrolled more than 100px
on the page. And that also makes a smooth jump
to the top of the page.
Improvements for the future
This is a fairly basic “back to top” button, but there are many improvements we can make, for example:
- Animations: We can add animations to the button to make it appear and disappear more smoothly (as on this blog).
- Custom styles: We can customize the button with styles more in line with our site.
And many other improvements we can make! But for now, this button is a good start to add a very useful functionality to our site.
I hope this tutorial has been helpful to you, and if you have any questions, don't hesitate to contact me at X or send me an email, or the contact form.