Create A Scroll Indicator With React
🚥

Create A Scroll Indicator With React

Description
A progress bar to show you how far you've scrolled inside your page
Tags
ReactJS
JS
Date posted
Mar 6, 2020
Image by
I don’t know about you, but I when I see some cool UI on a website I instantly feel like I want it on my website too. As part of our programming nature this is not for any reason other than because we can. So isn’t it cool when you see stuff like that.
 
notion image
 
 
Well I am going to show you how to build such a scroll indicator yourself! The good news is that it is quite simpler than you may think. It can be easily done with any Javascript framework but I am more comfortable to show you how to do it with React. I personally find that kind of progress bars very useful when reading (isn’t that why you’re here ts ts).
 
First things first we need to make a simple progress bar. I enjoy using styled-components but the logic is exactly the same whether you want to use emotion, css or any other preferred way of styling your components.
 
import React from "react"
import styled from "styled-components"

const ProgressBarWrapper = styled.div`
  width: 100%;
  height: 5px;
  top: 20px; // adjust it to the position you want
`

const ProgressBarBar = styled.div`
  background-color: red; // or any other color
  width: {props => props.progress}%;
`

const ProgressBar = ({ progress }) => (
  <ProgressBarWrapper>
    <ProgressBarBar progress={progress} />
  </ProgressBarWrapper>
)
 
This ProgressBar component only accepts one prop progress which is a number between 0 and 100. That will be the percentage of how filled our bar is. It is that simple and we also now know how progress bars work. Make sure you modify the colours and any further styling to match your likings. Now we need to add this to our web page. Our React page looks something like this.
 
import React, { useState } from 'react'

const BlogPage = () => {
  const [ progress, setProgress ] = useState(0)

  const handleScroll = (event) => {
     const { scrollTop, scrollHeight, clientHeight } = event.target
     setProgress((scrollTop * 100) / (scrollHeight - clientHeight))
  }

  ...
  return (
    <BlogWrapper onScroll={handleScroll}>
      <ProgressBar progress={progress} />
      ...
    </BlogWrapper>
  )
}
 
Let’s start with some simple useState hooks that will indicate the percentage of the page we have scrolled. In order to keep it simple, we start with 0 which also is the very beginning of the page. If you think about it, we have not started scrolled yey which translates to having reached 0% of the page. In a similar way, when we reach the very end we would have scrolled 100% of the page.
 
Now let’s talk about the core of how we fill up this progress bar. Have a look inside the handleScroll function. Do not worry if I have lost you, we will explain everything. Thankfully our best friend when it comes to web developer DOM has provided us with an onScroll event. onScroll lets us mess with the code that is executed every time we scroll through a certain element. The secret is to be careful about what element we are going to put that on.
 
If we inspect our web page, we will see that at some point there is an HTML element which has a reaaaally big height. That element is very likely to be your page’s content wrapper. That wrapper is the perfect place to add our scroll listener event on. That scroll event gives us access to some values that will allow us to read exactly where we are inside the page at any given time. To access these values, we need to dig deep into the event.target of the onScroll event.
 
We first have scrollHeight which tells us how many pixels the height of the entire element is. Then we have scrollTop which gives us how many pixels we have moved away from the beginning of the element. Last but not least we have clientHeight which gives us the height of our device’s screen.
 
It’s starting to make sense now isn’t it? Based on these variables we end up with formula like that:
 
(scrollTop * 100) / (scrollHeight - clientHeight)
 
That’s it. We now have a new simple and really slick navigation bar that know exactly how far off the end of the page we are and shows that with a nice indicator.