go to all blogs

In many modern websites you must have seen this effect of Navigation bar/ Header sticking to the top of the page even if you scroll down the page for your better navigation so you don't have to go up always to choose between links for moving between the pages. Haven't you?

If you have and are curious about how does that work, then this post is your go to guide to create that very simple yet beautiful effect/feature for you next project which adds better UX to the page.

What are you waiting for? Let's get started 🚀

Initial Setup

First we are going to create a react-app from start. For that enter this command in your favorite terminal

1create-react-app sticky-navbar

We are going to delete some of the files created out of the box from create-react-app. After deleting some files, project directory will look like this:

File structure

Starting file structure_

We will start by creating components, two components will suffice for this little project. Create a directory called Components in /src and add two files Navbar.js and Content.js

Start by editing App.js. Add following code to start with a basic layout

2import React from 'react'
4import Navbar from './components/Navbar'
5import Content from './components/Content'
7function App() {
8 return (
9 <div className="App">
10 <Navbar />
11 <Content />
12 </div>
13 )
16export default App

Here we are rendering two functional components Navbar and Content, their name clearly explains their purpose.

This below code fills up Navbar.js. Navbar component is basically a header section which consists of your website Logo and one navigation menu with 4/5 links

2import React from 'react'
3import './navbar.scss'
4import Logo from './../img/logo.svg'
6const Navbar = () => {
7 return (
8 <header className={navbarClasses.join(' ')}>
9 <div className="logo">{/* your logo */}</div>
11 <nav className="navigation">{/* your navigation */}</nav>
12 </header>
13 )
16export default Navbar

Now, it's time to give some styling to the page. You can have your own set of styling or if you just want to use mine, copy below given styles to navbar.scss

3.navbar {
4 width: 100%;
5 min-height: 6vh;
6 box-sizing: border-box;
7 display: flex;
8 justify-content: space-between;
9 align-items: center;
10 background-color: #eee;
11 transition: all 0.7s ease-in;
15.scrolled {
16 position: fixed;
17 top: 0;
18 left: 0;
19 background-color: lightblue;
21.logo img {
22 width: 50px;
25.navigation {
26 //your navigation styles

Now, we would fill up Content.js with some meat to add some content on the page along with the Navbar.

This code fills up dummy boxes to take ample amount of height on page. You can use any real life content. This is just for demo

3import React from 'react'
4import './content.scss'
6const Content = () => {
7 const data = (
8 <div className="box">
9 <h2>My div content </h2>
10 </div>
11 )
13 return (
14 <main className="content">
15 {data}
16 {data}
17 {data}
18 {data}
19 {data}
20 </main>
21 )
24export default Content

Style for Content.js

3.content {
4 width: 80%;
5 margin: 2rem 10% 0 10%;
6 max-width: 100%;
7 box-sizing: border-box;
8 min-height: 100vh;
10.box {
11 width: 80%;
12 margin: 2rem 10% 0 10%;
13 height: 100vh;
14 background-color: plum;

After all this setup, our page will look like this:

Complete layout

This is the visual after this much code

Main Logic

Now that we have our meat setup for the Sticky navbar, we will add the main Logic to get that sticky effect. For this we are going to do little bit of state-management using React hooks. If you are not aware of react-hooks, don't worry about it. You can use normal state management with classful component too.

So, the idea is as you scroll down, you check for the scrollY (i.e. total height you have scrolled from the top in pixels ) in componentDidMount() or useEffect() using window.scrollY and if that scrolled height is greater than some value, say 200px in this case, then we change the class of our Navbar to navbar scrolled. Styles for .scrolled is already in your navbar.scss if you have copied my styles. I have used array approach to switch between classes from navbar to navbar scrolled.

Confused ?

3import React,{useEffect} from 'react';
4import './navbar.scss';
6const Navbar=() => {
7 const [scrolled,setScrolled]=React.useState(false);
9 const handleScroll=() => {
10 const offset=window.scrollY;
11 if(offset > 200 ){
12 setScrolled(true);
13 }
14 else{
15 setScrolled(false);
16 }
17 }
19 useEffect(() => {
20 window.addEventListener('scroll',handleScroll)
21 })
23 let navbarClasses=['navbar'];
24 if(scrolled){
25 navbarClasses.push('scrolled');
26 }
28 return (
29 /* rest remains same*/
30 )
33export default Navbar;

In this way, we have successfully created our simple sticky Navbar from scratch.

If you want to look at the complete code, check my GitHub repo.


This was all for this simple demo application. I hope this post was helpful to you and I've solved your problem by explaining it in your words. If you have any queries regarding this post, feel free to ask me personally. I will be happy to answer those on individual level.

Thank you. Have a nice day!