React 18 On Scroll Sticky or Fixed Header Tutorial

Last Updated on by in React JS

In this tutorial, we will cover how to create sticky header using onScroll event handler in React js application.

To build the fixed header onScroll in React we will use functional component and the useLayoutEffect Hook.

Sticky headers are the constant headers. It is a general pattern for holding the header of a website or app at the same place on the screen when the user scrolls down the web page.

In general sticky header appears at the top position of the page when users scroll down the page.

How to Build onScroll Sticky Header in React using useLayoutEffect Hook

  • Step 1: Create React App
  • Step 2: Make Component File
  • Step 3: Create Sticky Header in React
  • Step 4: Style Fixed Header Layout
  • Step 5: Register Component in App Js
  • Step 6: View App in Browser

Create React App

In the first step, we will install the create react app tool in our system using the given command:

npm install create-react-app --global

Next, we have to run the command to install the new react project.

npx create-react-app react-demo

After the app is created, go inside the app’s folder.

cd react-demo

Make Component File

In the src/ folder, create a brand new folder named /components, in here create create the Layout.js file.

Put the following code into the file.

import React from 'react'

function Layout() {
  return (
    <div>Layout</div>
  )
}

export default Layout

Create Sticky Header in React

Open the components/Layout.js file and add the every code line by line in within the file.

import React, { useRef, useLayoutEffect } from 'react'

function Layout() {
  const stickyHeader = useRef()

  useLayoutEffect(() => {
    const mainHeader = document.getElementById('mainHeader')

    let fixedTop = stickyHeader.current.offsetTop

    const fixedHeader = () => {
      if (window.pageYOffset > fixedTop) {
        mainHeader.classList.add('fixedTop')
      } else {
        mainHeader.classList.remove('fixedTop')
      }
    }
    window.addEventListener('scroll', fixedHeader)
  }, [])

  return (
    <div>
      <div className="mainHeader" id="mainHeader" ref={stickyHeader}>
        <h2>React Js onScroll Sticky Header Example</h2>
      </div>
      <div className="main-block">
        <p>
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur
          lacinia pretium erat ac rutrum.
        </p>
        <p>
          Suspendisse in nulla augue pellentesque, lorem sed ullamcorper
          facilisis, tortor risus gravida arcu, nec tempor leo massa vel nisl.
        </p>
        <p>
          Nullam tincidunt est vitae tempus pretium. Sed diam tortor, luctus sed
          neque vel, vulputate vehicula nunc.
        </p>
        <p>
          Curabitur a vestibulum lorem, id hendrerit elit. Quisque vestibulum
          diam nisl, in tempus arcu varius at. Nulla placerat nibh quis mauris
          dapibus blandit. Maecenas sollicitudin sapien eget consequat viverra.
        </p>
        <p>
          Proin iaculis velit a velit luctus, at porta tortor tincidunt,
          Suspendisse non consectetur sem.
        </p>
        <p>
          Vestibulum ante ipsum primis in faucibus orci luctus et ultrices
          posuere cubilia curae; Sed varius bibendum nibh, nec vulputate est.{' '}
        </p>
        <p>
          Sed a ante luctus, faucibus est blandit, bibendum nisi. Sed non magna
          tellus.
        </p>
        <p>
          Ut semper egestas facilisis. Quisque porttitor vel metus sit amet
          dapibus.
        </p>
        <p>
          Maecenas sollicitudin dictum aliquam. Praesent iaculis ac tellus non
          iaculis. Interdum et malesuada fames ac ante ipsum primis in faucibus.
        </p>
        <p>
          Etiam interdum odio vel ipsum maximus suscipit. Ut at nunc a risus
          efficitur euismod. Phasellus blandit vehicula purus, rutrum pretium
          turpis commodo non.
        </p>
        <p>
          Integer ullamcorper faucibus dolor ut aliquam. Cras non nibh finibus,
          vestibulum turpis sed, congue risus. Duis maximus diam augue, ac porta
          nisi aliquet sit amet.{' '}
        </p>
        <p>
          Proin quis tortor at arcu pretium maximus. Donec sollicitudin pretium
          vestibulum. Nunc ut erat vestibulum, aliquet est at, fringilla elit.
          Integer vitae nisl diam. Nam vehicula pharetra congue.{' '}
        </p>
        <p>
          Vestibulum sed consequat ante. Phasellus lacinia erat eget interdum
          egestas. Fusce eu convallis lorem. Quisque pulvinar pulvinar justo.
        </p>
        <p>
          Donec suscipit ante vitae ante consectetur, at elementum tortor
          auctor. Nulla non congue nulla.
        </p>
        <p>
          Etiam tincidunt velit ligula, in lacinia augue tristique sed.
          Vestibulum consectetur lorem vitae quam vestibulum, in finibus turpis
          maximus.
        </p>
        <p>
          Quisque pellentesque purus diam, sed vestibulum odio consectetur ac.
          Orci varius natoque penatibus et magnis dis parturient montes,
          nascetur ridiculus mus.
        </p>
        <p>
          Nam egestas congue dignissim. Morbi porta congue augue, a faucibus ex
          tincidunt eget. Sed scelerisque dictum sapien eget tempus.
        </p>
        <p>
          Nulla dictum urna arcu, in dapibus sem sagittis sed. Donec metus nisi,
          imperdiet at nulla non, ornare porttitor lacus. Cras diam dolor,
          porttitor eget neque non, euismod eleifend enim.
        </p>
        <p>
          Ut neque ipsum, rutrum sed commodo nec, efficitur eu augue. Donec ac
          felis at ligula molestie fringilla. Cras vel mi orci. In et massa
          venenatis, molestie tellus sit amet, volutpat mi.
        </p>
      </div>
    </div>
  )
}

export default Layout

We need to calculate the header’s offset top value. The header’s offsetTop value is returning null, and we are getting a “Cannot read property ‘offsetTop’ of null” error.

The “mainHeader” value is executed before the component is rendered. We are trying to access the offsetTop property on a null value.

To tackle such a problem, we used the useLayoutEffect hook; It runs the JS script after the DOM elements are available.

It ensured only to access the property on valid DOM elements.

Register Component in App Js

Head over to src/App.js file, in here we need to import the Layout component in the App() function.

import './App.css'
import React from 'react'
import Layout from './components/Layout'

function App() {
  return (
    <div>
      <Layout />
    </div>
  )
}

export default App

Style Fixed Header Layout

Head over to App.css file, in this file you have to add the given CSS code. It will give looks and feel to sticky header layout of our React component.

.mainHeader {
  padding: 12px 18px;
  background: rgb(58, 15, 253);
  color: #fff;
  text-align: center;
}

.main-block {
  padding: 16px;
  max-width: 900px;
  margin: 0 auto;
  font-size: 18px;
}

.fixedTop {
  width: 100%;
  padding: 12px 18px;
  position: fixed;
  top: 0;
  background: rgb(251, 4, 235);
}

.fixedTop + .main-block {
  padding-top: 102px;
}

View App in Browser

In this last step, we will run the command and start the react server:

npm start

You have to open this url to view the app:

http://localhost:3000

React Js On Scroll Sticky or Fixed Header Tutorial

Conclusion

Sticky content normally hooks itself to the viewport when the user passes the header height. It remains intact at the top of the viewport.

In this React js sticky header example, we learned how to build the fixed header in React js when the user scrolls down.

We also learned how to use the useLayoutEffect React hook to create the fixed or sticky header with a function component.