Skip to main content

Add a "Back to top" button in React

Published ago
Updated ago
6 min read

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

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';
2
3export 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';
2
3export 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';
2
3export 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 };
11
12 return <button onClick={handleClick}>Back to top</button>;
13}
14
Note

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.

Tip

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';
2
3export default function BackToTopButton() {
4 const handleClick = () => {
5 window.scrollTo({
6 top: 0,
7 behavior: 'smooth',
8 });
9 };
10
11 return (
12 <button
13 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 top
19 </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';
3
4export default function BackToTopButton() {
5 const handleClick = () => {
6 window.scrollTo({
7 top: 0,
8 behavior: 'smooth',
9 });
10 };
11
12 return (
13 <button
14 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' />
20
21 <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 😉):

Tip

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';
3
4export default function BackToTop() {
5 const [showButton, setShowButton] = useState(false);
6
7 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 };
16
17 // Add the scroll event.
18 window.addEventListener('scroll', toggleVisibility);
19
20 // Clean the event when the component is unmounted.
21 return () => {
22 window.removeEventListener('scroll', toggleVisibility);
23 };
24 }, []);
25
26 const handleClick = () => {
27 window.scrollTo({ top: 0, behavior: 'smooth' });
28 };
29
30 return (
31 showButton && (
32 <button
33 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' />
37
38 <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.