reactjs responsive navbar

An Easy Way to Create a Responsive Navbar in ReactJS

Whenever we go to a web app, the navbar catches our attention first. So, creating a responsive navbar is important. In today's article, you will learn how to create a responsive Navbar in ReactJS. It will look perfect in all screen sizes, from larger desktops to 400px mobile screens. You can use this Navbar component in your landing pages, portfolios, and Dashboard, just by doing little customization.

We will talk about the mobile design once we will be done with the desktop version.

If you are only interested in code you can find it here on codepen;

Codepen Demo | ReactJS Responsive Navbar


ReactJS Navbar for Desktop

The navbar will look like this on Desktop screens.

navbar desktop UI

You have to create the basic Navbar component first. Here, the main nav tag will have two div, one for the logo and another for nav items or nav links.

import { ReactComponent as Brand } from '../../assets/icons/logo.svg'
const Navbar = () => {
return (
<nav>
<div>
<Brand />
</div>
<div>
<ul>
<li>Home</li>
<li>Blog</li>
<li>Projects</li>
<li>About</li>
<li>Contact</li>
</ul>
</div>
</nav>
)
}
export default Navbar

Reference

For the logo, I am using a mock logo from https://logoipsum.com/. You can use your logo.

Once we are done with base structure, we want our navbar links to navigate to specific routes, for that we need to wrap it inside anchor a tag.

import { ReactComponent as Brand } from '../../assets/icons/logo.svg'
const Navbar = () => {
return (
<nav>
<div>
<Brand />
</div>
<div>
<ul>
<li>
<a href="/">Home</a>
</li>
<li>
<a href="/blog">Blog</a>
</li>
<li>
<a href="/projects">Projects</a>
</li>
<li>
<a href="/about">About</a>
</li>
<li>
<a href="/contact">Contact</a>
</li>
</ul>
</div>
</nav>
)
}
export default Navbar

It looks fine. Right? No, It has a problem.

Problem

The whole page refreshes when we navigate to the given path or one page to another. It should work like a single-page app with smooth navigation.

Download React Router Dom

The solution to the problem is the Navlink component. It is used for internal linking in React. For this, we need to download react router dom Package in React application.

npm install react-router-dom@6

After downloading the package, import NavLink from react router dom and wrap nav item into NavLink instead of HTML anchor tag.

import { NavLink } from 'react-router-dom'
import { ReactComponent as Brand } from '../../assets/icons/logo.svg'
import './navbar.css'
const Navbar = () => {
return (
<nav className="navbar">
<div className="container">
<div className="logo">
<Brand />
</div>
<div className="nav-elements">
<ul>
<li>
<NavLink to="/">Home</NavLink>
</li>
<li>
<NavLink to="/blog">Blog</NavLink>
</li>
<li>
<NavLink to="/projects">Projects</NavLink>
</li>
<li>
<NavLink to="/about">About</NavLink>
</li>
<li>
<NavLink to="/contact">Contact</NavLink>
</li>
</ul>
</div>
</div>
</nav>
)
}
export default Navbar

With the navlink, you also have to import BrowserRouter and wrap the App component in it.

import { BrowserRouter } from 'react-router-dom'
import Navbar from './components/Navbar'
const App = () => {
return (
<BrowserRouter>
<Navbar />
</BrowserRouter>
)
}
export default App

React navbar highlights active page

What if you want to highlight the active page to know on which page are you?

What does React Router NavLink Do?

If we will inspect the DOM we will notice we still have an anchor tag but with some additional attributes or props. As soon we hit the link class="active" and aria-current="page" attributes applied to anchor tag.

navlink dom active class

As we know when we click the link it got active class. We can easily style the active class using CSS, so it looks bit different than other nav links.

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
body {
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
background-color: #fcfcfc;
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 15px;
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
}
.navbar {
height: 60px;
background-color: #fef7e5;
position: relative;
}
.logo {
}
.nav-elements {
}
.nav-elements ul {
display: flex;
justify-content: space-between;
list-style-type: none;
}
.nav-elements ul li:not(:last-child) {
margin-right: 60px;
}
.nav-elements ul a {
font-size: 16px;
font-weight: 400;
color: #2f234f;
text-decoration: none;
}
.nav-elements ul a.active {
color: #574c4c;
font-weight: 500;
position: relative;
}
.nav-elements ul a.active::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 100%;
height: 2px;
background-color: #574c4c;
}

What do you think, doesn’t NavLink have made our life easier?

Pro Responsive Tip

Look into the code that there is a div with a class container inside the nav tag. container class have max-width: 1100px , so navbar elements should not exceed 1100px when screen resizes.

Here I have tested in 1920 viewport.

navbar container for responsiveness

Congratulations, your desktop navbar design is ready.

Making Navbar Responsive

You can make the Navbar responsive in two ways. The first one uses CSS and another uses React.

  1. Using CSS: In CSS, you can simply change the display to none or block at your desired width to just completely change the HTML style.
  2. Using React: In React, you can use a useMediaQuery hook. You can learn more about React Custom hooks here.

You might be thinking what’s the difference and which one to use?

When we use CSS display: none property, the HTML remains in the DOM. On the other hand, the useMediaQuery hook does not have HTML in DOM. Remove JSX at a certain point from DOM to reduce its size.

Since this Navbar is not complex, so you can use CSS. It will make the code cleaner and easy to understand.

Become a better JavaScript developer by practicing only 10–20 minutes a week

Every Tuesday, you'll receive:

  • A JavaScript problem-solving challenge
  • Three conceptual JavaScript MCQs
Subscribe to JS Bytes

Mobile Screen Navbar Design

Your Navbar should look like this on the Mobile.

navbar mobile design

The logo will be in its place, but instead of nav items (nav links), we will have hamburger icon, by pressing hamburger icon, nav links will slide from the right side of the screen.

For toggling nav elements we need to have a state and toggle function. The only state and function we need for this component.

const [showNav, setShowNav] = useSate(false)
const toggleNavItems = () => {
setShowNav(!showNav)
}

As we know by clicking the hamburger icon nav elements will slide from the right side of the screen.

So at 600px we are changing .nav-elements class styles.

.nav-elements {
position: absolute;
right: 0;
top: 60px;
background-color: #fef7e5;
width: 0;
height: calc(100vh - 60px);
transition: all 0.3s ease-in;
overflow: hidden;
}

You can look into the code that the position of .nav-elements is absolute. We also have to adjust it on the right of the screen. The width is 0 as the active class will make the width 270px. You can adjust the size as per your requirements.

Moving to the Sidebar animation Now!

When we invoke the toggleNavItems function on the hamburger, set showNav to true. When the showNav is true, show the sidebar containing the nav links. You can do it by adding the .active class to it.

const Navbar = () => {
const [showNavbar, setShowNavbar] = useState(false)
const handleShowNavbar = () => {
setShowNavbar(!showNavbar)
}
return (
<nav className="navbar">
<div className="container">
<div className="logo">
<Brand />
</div>
<div className="menu-icon" onClick={handleShowNavbar}>
<Hamburger />
</div>
<div className={`nav-elements ${showNavbar && 'active'}`}>
<ul>...</ul>
</div>
</div>
</nav>
)
}
export default Navbar

Style for Mobile Screen Navbar

@media (max-width: 600px) {
.menu-icon {
display: block;
cursor: pointer;
}
.nav-elements {
position: absolute;
right: 0;
top: 60px;
background-color: #fef7e5;
width: 0px;
height: calc(100vh - 60px);
transition: all 0.3s ease-in;
overflow: hidden;
}
.nav-elements.active {
width: 270px;
}
.nav-elements ul {
display: flex;
flex-direction: column;
}
.nav-elements ul li {
margin-right: unset;
margin-top: 22px;
}
}

Before going ahead, we should understand two points. As you can see, the viewport is 600px.

  1. Initially .menu-icon was display: none so we made it display: block to make it visible
  2. We have also added .active class that makes sidebar width: 270px

React Responsive Navbar Complete Component

import { useState } from 'react'
import { NavLink } from 'react-router-dom'
import { ReactComponent as Hamburger } from '../../assets/icons/hamburger.svg'
import { ReactComponent as Brand } from '../../assets/icons/logo.svg'
import './navbar.css'
const Navbar = () => {
const [showNavbar, setShowNavbar] = useState(false)
const handleShowNavbar = () => {
setShowNavbar(!showNavbar)
}
return (
<nav className="navbar">
<div className="container">
<div className="logo">
<Brand />
</div>
<div className="menu-icon" onClick={handleShowNavbar}>
<Hamburger />
</div>
<div className={`nav-elements ${showNavbar && 'active'}`}>
<ul>
<li>
<NavLink to="/">Home</NavLink>
</li>
<li>
<NavLink to="/blog">Blog</NavLink>
</li>
<li>
<NavLink to="/projects">Projects</NavLink>
</li>
<li>
<NavLink to="/about">About</NavLink>
</li>
<li>
<NavLink to="/contact">Contact</NavLink>
</li>
</ul>
</div>
</div>
</nav>
)
}
export default Navbar

CSS for Responsive Navbar

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
body {
margin: 0;
padding: 0;
font-family: 'Poppins', sans-serif;
background-color: #fcfcfc;
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 0 15px;
display: flex;
justify-content: space-between;
align-items: center;
height: 100%;
}
.navbar {
height: 60px;
background-color: #fef7e5;
position: relative;
}
.logo {
}
.menu-icon {
display: none;
}
.nav-elements {
}
.nav-elements ul {
display: flex;
justify-content: space-between;
list-style-type: none;
}
.nav-elements ul li:not(:last-child) {
margin-right: 60px;
}
.nav-elements ul a {
font-size: 16px;
font-weight: 400;
color: #2f234f;
text-decoration: none;
}
.nav-elements ul a.active {
color: #574c4c;
font-weight: 500;
position: relative;
}
.nav-elements ul a.active::after {
content: '';
position: absolute;
bottom: -4px;
left: 0;
width: 100%;
height: 2px;
background-color: #574c4c;
}
@media (max-width: 768px) {
.nav-elements ul li:not(:last-child) {
margin-right: 30px;
}
}
@media (max-width: 600px) {
.menu-icon {
display: block;
cursor: pointer;
}
.nav-elements {
position: absolute;
right: 0;
top: 60px;
background-color: #fef7e5;
width: 0px;
height: calc(100vh - 60px);
transition: all 0.3s ease-in;
overflow: hidden;
}
.nav-elements.active {
width: 270px;
}
.nav-elements ul {
display: flex;
flex-direction: column;
}
.nav-elements ul li {
margin-right: unset;
margin-top: 22px;
}
}

Further Read

If you're looking for multiple variations of a React responsive navbar component built with Tailwind CSS and TypeScript, find them here.

You have successfully created a ReactJS responsive navbar component. I hope this has helped you to learn the easy way to create and reuse the ReactJS responsive navbar component. Feel free to use this code in your projects.

Read Next

Codevertiser Magazine

Subscribe for a regular dose of coding challenges and insightful articles, delivered straight to your inbox