How to Build a Hamburger Menu in React

How to Build a Hamburger Menu in React

·

12 min read

Navigation menus are often one of the first components developers create during web development, primarily because they enhance the user's understanding of a website's structure and content. In this tutorial, you'll learn how to build a responsive navigation or hamburger menu using React. To fully benefit from this tutorial, it's helpful to already have experience creating responsive navigation menus with JavaScript, HTML, and CSS.

What You’re Building

Here’s a glimpse of what you’ll have by the end of this tutorial:

You can customize the style and content of the navigation menu to suit your needs, but the core functionality will remain the same.

Prerequisites

To follow along, you should have a basic understanding of the following:

  • Props and state in React

  • CSS media queries

  • How to use the terminal

In addition to those, you need a code editor and a web browser. This tutorial uses Visual Studi Code and Google Chrome, but any code editor and web browser will work.

Setting Things Up

Follow the steps in this section to set up the project's environment. If you have already created a React app, skip the first three steps below.

  1. Install NodeJS

    Open the terminal in your code editor and run the following command to check if NodeJS is installed on your device:

     node -v
    

    If a version number is returned, NodeJS is correctly installed. Otherwise, download and install NodeJS before continuing.

  2. Create a React App

    Using the terminal, navigate to the directory where you want to locate your app, then run the following command to create a new React application.

     npx create-react-app myapp  
    
     // myapp above is the name of your project
    
  3. Open the Project Folder

    Once your app has been successfully created, open it by running:

     cd myapp
    
  4. Start the App

    Run the following command to start your new or existing React app:

     npm start
    

    Ensure you are inside your app’s folder in the terminal before running the command above.

  5. Install Dependencies

    For this project, you need the React Icons package. It allows you to use custom-made icons in your project. To install React Icons, run the following command:

     npm install react-icons
    
  6. Clear Unnecessary Files

    Create React App installs some default files and content. To remove the unnecessary ones, do the following:

    • Delete the logo.svg file.

    • In the src folder, locate the App.js and App.css files and delete their contents.

In the next section, you will start building the hamburger menu. Be sure to follow each step in order, as skipping any steps may lead to errors.

Building a Responsive Hamburger Menu in React

This section will guide you through building a fully responsive hamburger menu. Before proceeding, note that in React, the term component refers to a file with specific functionality. Consequently, the terms file and component will be used interchangeably in this section.

Step 1: Create a Parent Folder

You need a parent folder to hold all the components of your project, not just the navigation menu. To create one, follow these steps:

  • Locate the src folder in the file tree.

  • Create a new folder within the src folder and name it Components.

Step 2: Create a Subfolder

Within the Components folder, create a new subfolder named NavBar. This folder will contain all files related to your navigation menu.

Step 3: Create Components

Within the NavBar folder, create the following files:

  1. NavBar.css

    Create a file named NavBar.css that will contain the style rules for the navigation menu.

  2. NavLinks.js

    Create a file named NavLinks.js and import the NavBar.css file into it. For now, this component will be a stateless function component that returns a list of menu items.

     //NavLinks.js
    
     import './NavBar.css';
    
     const NavLinks = () =>{
         return(
             <nav className="NavLinks">
             <ul>
                 <li>
                     <a href="/">Home</a>
                 </li>
                 <li>
                     <a href="/#services">Services</a>
                 </li>
                 <li>
                     <a href="/#about">About Us</a>
                 </li>
                 <li>
                     <a href="/#contact">Contact Us</a>
                 </li>
             </ul>
         </nav>
         )
     }
    
     export default NavLinks;
    
  3. DesktopNavigation.js

    Create a new file named DesktopNavigation.js. This file will also be a stateless function component with the following content:

     //DesktopNavigation.js
    
     import NavLinks from "./NavLinks";
     import './NavBar.css';
    
     const DesktopNavigation = () =>{
         return()
     }
    
     export default DesktopNavigation;
    
     // Note that NavBar.css and NavLinks.js are imported here
    

    In the return block of this component, add an element to render the text “Logo” to the browser. This will serve as the app’s logo. If you have an image, use the <img> tag instead of the <h2> tag used below:

     <h2 className="logo">Logo</h2>
    

    Render the NavLinks component you imported, then wrap everything in a <nav> tag with a class name of DesktopNavigation. The final code for the DesktopNavigation component should look like this:

     //DesktopNavigation.js
    
     import NavLinks from "./NavLinks";
     import './NavBar.css';
    
     const DesktopNavigation = () =>{
         return(
             <nav className="DesktopNavigation">
                 <h2 className="logo">Logo</h2>
                 <NavLinks />
             </nav>
         )
     }
    
     export default DesktopNavigation;
    
  4. NavBar.js

    Create a new file named NavBar.js, then import and render the DesktopNavigation component within it as follows:

     //NavBar.js
    
     const NavBar = () => {
         return()
     }
    
     export default NavBar;
    
     //leave the return block empty for now
    

Step 4: Render the NavBar to the Browser

In the App.js file, import and render the NavBar component as follows:

//App.js

import NavBar from './../Components/NavBar/NavBar';

function App() {
  return (
    <NavBar />
  );
}

export default App;

//The import statement above is different from other imports 
//you have done so far because App.js lives outside 
//the NavBar container you created for this navigation menu.

An unstyled navigation menu should now be visible in your browser, as shown below:

Step 5: Style the Navigation Menu

Before applying style rules to the navigation menu, locate the index.css file in the file tree and paste the following code into it:

/*Index.css*/

*{
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

/* This ensures that default browser styling doesn't affect your app

Then, copy the code below and paste it into your NavBar.css file, or apply your own custom styling.

/*NavBar.css*/

nav{
    display: flex;
    align-items: center;
    justify-content: space-evenly;
    background: aqua;
    padding: 30px 50px 30px 50px;
}

.NavLinks{
    height: 15vh;
}

nav ul{
    display: flex;
    flex-direction: row;
    justify-content: space-evenly;
}

nav ul li{
    list-style-type: none;
    display: inline-block;
    padding: 10px 20px;
}

nav ul li a{
    text-decoration: none;
    font-weight: bold;
    color: black;
}

nav ul li a:hover{
    color: white;
    transition: .3s;
}

/*You can style yours differently

Check your browser to ensure that the specified styles have been applied. You should have something close to the image below:

Step 6: Add a Mobile Navigation Component

So far, you’ve created a desktop navigation menu. Now, to accommodate mobile users, follow these steps:

  1. Create a new file named MobileNavigation.js.

  2. Copy the content of DesktopNavigation.js and paste it into MobileNavigation.js.

  3. Replace every instance of DesktopNavigation with MobileNavigation in the code you copied.

Step 7: Render the MobileNavigation Component

In the NavBar component, import and render the MobileNavigation component as shown below:

//NavBar.js

import DesktopNavigation from './DesktopNavigation';
import MobileNavigation from './MobileNavigation';

const NavBar = () => {
    return(
        <div>
            <DesktopNavigation />
            <MobileNavigation />
        </div>
    )
}

export default NavBar;

Since MobileNavigation and DesktopNavigation are identical components, you should now see duplicate navigation menus in the browser:

Ideally, you should render only one of DesktopNavigation or MobileNavigation based on the user's screen size, not both at once. You’ll address this issue with CSS in the next step.

Step 8: Fix the Duplicate Navigation Menus

In the NavBar.css file, set the display property to none for the MobileNavigation class:

/*NavBar.css*/

.MobileNavigation{
    display: none;
}

/*This takes the MobileNavigation component away from the browser.

Step 9: Make the Navigation Menu Responsive

Currently, the MobileNavigation component is hidden. You want to ensure it is visible on mobile devices while hiding the DesktopNavigation component. To achieve this, update the NavBar.css file with the following media query:

/*NavBar.css*/

@media (max-width: 768px){

    .DesktopNavigation{
        display: none;
    }

    .MobileNavigation{
        display: flex;
        align-items: center;
        height: 15vh;
        background-color: red;
    }

    .NavLinks{
       background-color: red; 
    }
}

/*the height property within this media query should be equal to the height
 of the NavLinks classname

Resize your browser to confirm that the media query is active. You can verify this by checking if the background color changes at the specified breakpoint of 768px.

Step 10: Add a Hamburger Icon

A hamburger icon is a more conventional way to represent a navigation menu on mobile devices. To implement this functionality using the react-icons package you installed earlier, do the following:

  1. Visit the React Icons website.

  2. Search for "menu" in the search bar.

  3. Browse the search results to find a hamburger icon you like.

  4. Click on the icon to copy its name to your clipboard.

  5. Open your MobileNavigation component and import the icon using the following syntax:

     //MobileNavigation.js 
    
     import {MdOutlineMenu} from 'react-icons/md'
    
     /*Append the first two letters of an icon's name to the end of the import statement. 
     The letters "md" was added to 'react-icons/' because we imported 'MdOutlineMenu'
    
  6. Create a variable named Hamburger and embed the imported icon within it. Assign a class name of HamburgerMenu to the icon, and specify values for its size and color as follows:

     //MobileNavigation.js
    
     const Hamburger = <MdOutlineMenu className="HamburgerMenu"
                size="30px" color="black"/>
    
  7. Lastly, render the Hamburger variable within the MobileNavigation component. Your code should be similar to the following:

     //MobileNavigation.js 
    
     import NavLinks from "./NavLinks";
     import './NavBar.css';
     import {MdOutlineMenu} from 'react-icons/md';
    
     const Hamburger = <MdOutlineMenu className="HamburgerMenu"
                size="30px" color="black"/>
    
     const MobileNavigation = () =>{
    
         return(
             <nav className="MobileNavigation">
                  <h2 className="logo">Logo</h2>
                  {Hamburger}
                  <NavLinks />                         
             </nav>
         )
     }
    
     export default MobileNavigation;
    

Step 11: Position the Hamburger Icon

You need to position the hamburger icon to the far right of the navigation menu. To achieve this, locate the media query block in NavBar.css and add the following properties to the HamburgerMenu class:

/*index.css*/

.HamburgerMenu{
        position: absolute;
        right: 2%;
        cursor: pointer;
    }

/*This code block should be located within your media query.

You should now see the hamburger icon positioned on the far right of the navigation menu in your browser, as shown below:

Step 12: Make the Hamburger Icon Functional

To make the hamburger icon functional, you'll need to attach an event listener to it. This event listener will trigger a function each time a user clicks on the icon. For now, you can log "click" to the console:

//MobileNavigation.js 

const Hamburger = <MdOutlineMenu className="HamburgerMenu"
           size="30px" 
           color="black"
           onClick={() => console.log("click")} />

Confirm that the onClick event is functional by inspecting your browser’s console:

To enable the hamburger icon to toggle the navigation menu on and off when clicked, import the useState hook into your MobileNavigation component as follows:

//MobileNavigation.js 

import { useState } from "react";

Next, define a state within the MobileNavigation component:

//MobileNavigation.js 

const [click, setClick] = useState(false);

//the state above is initialized to "false"

Within the onClick event, call setClick and pass !click to it as an argument. This will toggle the state’s value each time the user clicks on the hamburger icon:

//MobileNavigation.js 

const Hamburger = <MdOutlineMenu className="HamburgerMenu"
           size="30px" 
           color="black"
           onClick={() => setclick(!click)} />

/*
1. The console.log you had before has been replaced with the 
state setter function (i.e setClick)

2. The exclamation mark in setClick's argument above is 
responsible for toggling the state's value between true/false.

Next, specify a condition that determines what to display based on the state’s value. You want React to display the NavLinks component if the state’s value is true; otherwise, nothing should be displayed. Here’s how to set that up:

//MobileNavigation.js 

<nav className="MobileNavigation">
    <h2 className="logo">Logo</h2>
    {Hamburger}
    {click && <NavLinks />} // pay attention to this line
</nav>

For now, your MobileNavigation component should look like this:

At this point, your hamburger icon should toggle the navigation menu on and off when clicked.

Step 13: Add a "Close" Icon to MobileNavigation

In mobile view, users need an icon to click on to hide the menu items displayed by the hamburger icon. To implement this, follow these steps:

  1. Revisit the react-icons website.

  2. Search for the term "close."

  3. In the search results, find your preferred icon and click on it to copy its name to your clipboard.

  4. Import the icon into your MobileNavigation component, just as you did with the hamburger icon:

     //MobileNavigation.js 
    
     import {MdClose} from 'react-icons/md';
    
     //append 'md' to 'react-icons'
    
  5. Below the Hamburger variable, create a new variable named Close.

  6. Copy the content of the Hamburger variable and paste it into the Close variable.

  7. Edit the code by replacing MdOutlineMenu with MdClose. Your code should look like this:

     //MobileNavigation.js
    
     const Close = <MdClose className="HamburgerMenu"
                 size="30px" color="black"
                onClick={() => setclick(!click)} />
    
  8. In the return block, use a ternary operator to conditionally render either the Hamburger or Close icon based on the state:

     //MobileNavigation.js
    
     return(
             <nav className="MobileNavigation">
                  <h2 className="logo">Logo</h2>
                  { click ? Close : Hamburger} 
                  {click && <NavLinks }/>}
             </nav>
         )
    

For clarity, your MobileNavigation component should look like this:

//MobileNavigation.js

import NavLinks from "./NavLinks";
import './NavBar.css';
import {MdOutlineMenu} from 'react-icons/md'
import { useState } from "react";
import {MdClose} from 'react-icons/md';


const MobileNavigation = () =>{
    const [click, setclick] = useState(false);

    const Hamburger = <MdOutlineMenu className="HamburgerMenu"
           size="30px" color="black"
           onClick={() => setclick(!click)} />

    const Close = <MdClose className="HamburgerMenu"
            size="30px" color="black"
           onClick={() => setclick(!click)} />

    return(
        <nav className="MobileNavigation">
             <h2 className="logo">Logo</h2>
             { click ? Close : Hamburger}
             {click && <NavLinks />}
        </nav>
    )
}

export default MobileNavigation;

Step 14: Style the Mobile Navigation

You now have a functional navigation menu, but it doesn't behave like the typical menu you might expect. To fix that, go to the media query in your NavBar.css file and do the following:

  1. Remove the background-color property you previously assigned to the MobileNavigation and NavLinks class names.

  2. Assign the following properties to the ul element:

     .NavLinks ul{
             display: flex;
             flex-direction: column;
             justify-content: space-evenly;
             position: absolute;
             border-top: 3px solid orange;
             top: 15vh;
             right: 0;
             height: 50vh;
             width: 100%;
             background:blue;
         }
    

    Ensure that the top value in the CSS style above matches the height value you assigned to the NavLinks class name in Step 5. This alignment ensures that your mobile menu renders just below the navigation bar. See it in action below:

Step 15: Tidying Up

The project is almost complete, but there's one issue: the navigation menu doesn't close when you select any of its items. To fix that, follow these steps:

  1. In the MobileNavigation component, within the Close variable, define a function called closeMenu. This function will set the state value to false when called:

     const closeMenu = () => setclick(false);
    
     /* The mobile navigation menu will go away
     when the state’s value is false.
    
  2. Since the mobile navigation menu will disappear when the state’s value is false, you need a way to trigger the closeMenu function when a menu item is selected. You can achieve this by passing props to the NavLinks component as follows:

     {click && <NavLinks isClicked={true} closeMenu={closeMenu}/>}
    
  3. Go to the NavLinks component and receive the props:

     const NavLinks = ({isClicked, closeMenu}) => {
         return ( 
             <nav className="NavLinks">
             <nav/>
         )
    
  4. Then, attach an onClick event to each of the list items, passing in both the isClicked and closeMenu props. Your final code should look like this:

If you’ve made it this far, congratulations on successfully building a fully responsive hamburger menu in React!

Conclusion

In this tutorial, you learned how to build a responsive hamburger menu using React. While this approach is one of many ways to create navigation menus, it's a solid starting point for beginners. If you're already familiar with building responsive menus using plain JavaScript, comparing that knowledge with this React-based approach can deepen your understanding of both techniques.