Learn how to create scroll indicator in react.
Scroll indicator is used to indicate how much of a page has been scrolled, so that user gets a good idea about what is the length of the content.
To create this component we need few extra packages.
classnames
: This helps us to use CSS classes as javascript objects, we just need to name our CSS file asfilename.module.css
Following is the folder structure of our component.
As you now know what we have to built, so lets dig in and start building it.
Import all the required packages and setup the structure.
import React, { Component } from "react"; import styles from "./index.module.css"; class ScrollIndicator extends Component { //Other code will go here } export default ScrollIndicator;
We have created a stateful component because we need to maintain the state of scroll position of the component.
To calculate the amount of page scrolled, we have to first listen to the scroll event so that we get the required values for calculation.
Assign the event listener when the component is mounted inside the componentDidMount
life cycle method.
componentDidMount() { window.addEventListener("scroll", this.calculateScrolledInPercentage); }
Now we need to calculate the percentage and store the data in state so that component is updated properly after scroll position is changed.
state = { scrolledPercentage: 0 }; calculateScrolledInPercentage = () => { //How much scrolled const winScroll = document.body.scrollTop || document.documentElement.scrollTop; //Full height const height = document.documentElement.scrollHeight - document.documentElement.clientHeight; //Percentage scrolled const scrolledPercentage = (winScroll / height) * 100; //Update state this.setState({ scrolledPercentage }); };
We are calculating percentage scrolled relative to root parent rather than any specific element that is why we are getting the scroll position of body or documentElement
which is html
tag.
Once we have the scrolled position, let us now render the layout.
render() { const { scrolledPercentage } = this.state; return ( <div className={styles.header}> <h1>Scroll Indicator</h1> <div className={styles.progressContainer}> {/* Update the width in percentage */} <div className={styles.progressBar} style={{ width: `${scrolledPercentage}%` }} ></div> </div> </div> ); }
The last thing pending is memory clean up, when the component is about to be removed remove the listener. We can use the componentWillUnmount
method.
componentWillUnmount() { window.removeEventListener("scroll", () => {}); }
Complete code of react scroll indicator
import React, { Component } from "react"; import styles from "./index.module.css"; class ScrollIndicator extends Component { state = { scrolledPercentage: 0 }; calculateScrolledInPercentage = () => { //How much scrolled const winScroll = document.body.scrollTop || document.documentElement.scrollTop; //Full height const height = document.documentElement.scrollHeight - document.documentElement.clientHeight; //Percentage scrolled const scrolledPercentage = (winScroll / height) * 100; //Update state this.setState({ scrolledPercentage }); }; componentDidMount() { window.addEventListener("scroll", this.calculateScrolledInPercentage); } componentWillUnmount() { window.removeEventListener("scroll", () => {}); } render() { const { scrolledPercentage } = this.state; return ( <div className={styles.header}> <h1>Scroll Indicator</h1> <div className={styles.progressContainer}> {/* Update the width in percentage */} <div className={styles.progressBar} style={{ width: `${scrolledPercentage}%` }} ></div> </div> </div> ); } } export default ScrollIndicator;
Complete style code
The styling for this component is extremely simple, we have positioned the indicator div as an absolute inside a relative parent and width of it will be dynamically updated through code.
.header { position: fixed; top: 0; z-index: 1; width: 100%; background-color: #f44336; text-align: center; box-shadow: 0 1px 3px #000; } /* The progress container (grey background) */ .progressContainer { width: 100%; height: 8px; background: #ccc; } /* The progress bar (scroll indicator) */ .progressBar { height: 8px; background: #4caf50; width: 0%; transition: width 0.2s linear; }
Input
import React from "react"; import ReactDOM from "react-dom"; import "./index.css"; import ScrollIndicator from "./Components/ScrollIndicator"; import * as serviceWorker from "./serviceWorker"; ReactDOM.render( <div className="abc"> <ScrollIndicator /> </div>, document.getElementById("root") ); // If you want your app to work offline and load faster, you can change // unregister() to register() below. Note this comes with some pitfalls. // Learn more about service workers: https://bit.ly/CRA-PWA serviceWorker.unregister();