How to create a page scroll progress bar
In this quick tutorial you will learn how to create a simple scroll progress bar using React step by step.
It's supposed that you have already have your configured project. If you don't have one, I recommend install React via Create React App
Step 1: Create a component in your project directory
For example, I created <ProgressScroll> component folder. There are two files inside: the component file itself ProgressScroll.tsx
and the style file progress-scroll.module.scss
. As you can see I'm using TypeScript and Sass, but feel free and use any syntax and preprocessor you want, it will not affect the result.
.
└── Your awesome project/
└── src/
└── components/
└── ProgressScroll/
├── ProgressScroll.tsx
└── progress-scroll.module.scss
The code below is an example of an empty component. Next we will add some ✨code✨ to this file.
1import React, { ReactElement } from 'react';
2
3export const ProgressScroll = (): ReactElement => {
4 return (
5 <div></div>
6 );
7};
Step 2: Add a progress state
To display scrolling progress we need to store scroll progress somewhere. React Hook useState
is ideal for it. Add a state [progress, setProgress]
to your component. Don't forget to import useState
.
1import React, { ReactElement, useState } from 'react';
2
3export const ProgressScroll = (): ReactElement => {
4 const [progress, setProgress] = useState<number>(0);
5
6 return (
7 <div></div>
8 );
9};
The first value, progress
, is our scroll progress value or how many percent did we scroll down the page. The second value, setProgress
, is the function that is used to update our state.
Step 3: Add some style
Before we add magic let's style our scroll progress bar. Check the code below, there are updated markup:
1import React, { ReactElement, useState } from 'react';
2
3import styles from './progress-scroll.module.scss';
4
5export const ProgressScroll = (): ReactElement => {
6 const [progress, setProgress] = useState<number>(0);
7
8 return (
9 <div className={styles.progressScroll}>
10 <div
11 className={styles.progressScroll__bar}
12 style={{ width: `${progress}%` }} />
13 </div>
14 );
15};
Of course we need to add some style:
1.progressScroll {
2 position: fixed;
3 top: 0;
4 z-index: 10000;
5 width: 100%;
6 height: 5px;
7 background: LightGray;
8
9 &__tracker {
10 height: 100%;
11 background-color: DarkViolet;
12 transition: 0.5s width;
13 }
14 }
A few notes on the style. z-index
should be such that the scroll progress bar appears on top of all elements on your page. height
, background
and background-color
can be anything you like.
If you run the component now, you will just see a gray bar at the top of the page. It's time for magic!
Step 4: Add magic
It's right around the corner. Before we added the scroll progress state. Now let's add a function that will calculate scrolling progress: handleScroll()
. Also we will use useEventListener
hook. It's a custom hook that attaches event listeners to DOM elements, the window, or media query lists. You can check it here. About React custom hooks you can read here.
1import React, { ReactElement, useState } from 'react';
2import useEventListener, { Event } from 'src/hooks/useEventListener';
3
4import styles from './progress-scroll.module.scss';
5
6export const ProgressScroll = (): ReactElement => {
7 const [progress, setProgress] = useState<number>(0);
8
9 const handleScroll = (): void => {
10 const height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
11 const scrolledHeight = window.scrollY;
12 const scrolledPercent = Math.round((scrolledHeight * 100) / height);
13
14 setProgress(scrolledPercent);
15 };
16
17 useEventListener(Event.SCROLL, handleScroll);
18
19 return (
20 <div className={styles.progressScroll}>
21 <div
22 className={styles.progressScroll__bar}
23 style={{ width: `${progress}%` }} />
24 </div>
25 );
26};
We will receive via DOM Event Listener
in handleScroll()
an information about scroll height and client height after each scroll. Here is difference between scroll height and client height:
Then using the formula above we calculate the scrolling progress. If you want to see the final result just look at the top of this page and scroll up and down.
Read more
Thanks for reading!