How to build a hamburger menu in React

How to build a hamburger menu in React

·

13 min read

Mobile phones now account for over 55 per cent of the world’s web traffic. With this reality, responsive navigation has become a critical part of modern websites. In this tutorial, you'll learn how to build a responsive hamburger (navigation) menu in ReactJS.

The content that follows was written with new React developers in mind, therefore, experienced developers may not find the content very useful. Furthermore, this tutorial only covers navigation in ReactJS, it'll not teach you how to build navigation menus in vanilla JavaScript.

Table of contents

  • What you are building

  • Prerequisites

  • Tools needed

  • Setting things up

  • Steps to build a responsive navigation menu in React

  • Tidying up

  • Conclusion

What you are building

The following is what the final project will look like. You can switch things up in your project to make it look different, but the functionality will be the same.

Prerequisites

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

  • Props and state in React

  • CSS media query

  • The command line

Tools needed

In addition to the prerequisite knowledge required, you also need the following tools:

  • A new or existing React app

  • A code editor

  • A web browser

You'll create a new React app in the next section if you don't have one already. While it's safe to assume you already have a web browser, you can download Google Chrome for desktops if you don't. Visual Studio Code is the code editor used here, but any other editor works fine.

Setting things up

This section will help you set things up. If you already have a React app, skip the first two steps below.

  1. Create a React app

    Confirm if NodeJS is installed on your device by running the command: node -v from your terminal. If a version number is returned, you are good. Otherwise, download and install NodeJS first before continuing. Once the installation is complete, create a new React application by running the following command:

     npx create-react-app myapp
    
     // myapp above is the name of your project
    
  2. Open the project folder

    Within your command line, navigate to your project's folder:

     cd myapp
    
  3. Start the app
    Run the following command to start your new or existing app:

     npm start
    
  4. Install packages

    For this project, you need the following packages:

    • React-icons: This package lets you use custom-made icons in your project. To install react-icons, run the command below:

        npm install react-icons
      
        //ensure you're inside your project directory:
      
  5. Clear irrelevant files

Now you are all set, it's time to start building your hamburger menu project.

Steps to build a responsive hamburger Menu in React

The following steps will guide you on how to build a responsive hamburger menu in React. Unless explicitly stated, the terms: file and component refer to the same idea in this section.

Step 1: Create a new folder

Follow the steps below to create a parent folder for the entire project:

  1. Open the project folder in a code editor

  2. Locate the src folder

  3. Create a new folder named Components

Step 2: Create a subfolder

Within the Components folder, create another new folder named NavBar. It's a parent folder that'll hold files relevant to your hamburger menu.

Step 3: Create components

Within the NavBar folder, create the following components:

  1. NavBar.css

    Create a new file named NavBar.css. It'll be a container for the navigation menu styles.

  2. NavLinks

    Create another new file named NavLinks.js and import the NavBar.css file you created earlier into it. For now, this component will be a stateless function component that only returns an unordered list of the items. The content of the unordered list should be what you intend to have in your navigation menu:

     //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;
    
     //You'll style this component by targetting the NavLinks classname above
    
  3. DesktopNavigation

    Create a new file and save it as DesktopNavigation.js. It'll 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, do the following:

    • Add a h2 element that'll render the text "Logo" to the browser. This h2 element, with a class name of "logo," will serve as the logo for this project:

        <h2 className="logo">Logo</h2>
      
    • Render the NavLinks component you imported:

        <NavLinks />
      
    • Wrap both imports above in a nav tag and add a class name of DesktopNavigation to the tag:

        <nav className="DesktopNavigation">
                    <h2 className="logo">Logo</h2>
                    <NavLinks />
        </nav>
      

      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

    Create a new file named NavBar.js:

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

Step 4: Import DesktopNavigation

In the NavBar.js file you just created, import and render the DesktopNavigation component:

//NavBar.js

import DesktopNavigation from './DesktopNavigation';

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

export default NavBar;

Step 5: Render to the browser

Go to the App.js file and import the Navbar component:

//App.js

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

//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.

Next, render the imported Navbar component within the return block of your App.js file:

//App.js

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

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

export default App;

An unstyled navigation menu should now be visible in your browser. You'll add styling to it in the next step.

Step 6: Style the navigation menu

To style the navigation menu, you'll copy style rules from this section and paste them into your NavBar.css file. But before that, locate the index.css file in the file tree and paste the following into it:

/*Index.css*/

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

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

Next, fill up the content of your NavBar.css with the following:

/*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

That settles the styling for your navigation menu. Check the browser to ensure you have something close to the image below:

Step 7: Add a Mobile Navigation Component

Until now, you've been working on a menu for desktop and large-screen devices. It's now time to set up a separate menu for mobile devices. To do that, follow the steps below:

  1. Create a new file and save it as MobileNavigation.js.

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

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

Step 8: Render the MobileNavigation component

Within the NavBar component, import and render MobileNavigation:

//NavBar.js

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

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

export default NavBar;

Because you returned both DesktopNavigation and MobileNavigation in the NavBar component above, you should be seeing duplicate navigation menus in the browser:

Ideally, you only want to render one of either DesktopNavigation or MobileNavigation (depending on the user's device) - not the two at once. You'll fix this with CSS next.

Step 9: Fix the duplicate navigation menu

In the NavBar.css file, grab the MobileNavigation classname and assign a display value of none to it:

/*NavBar.css*/

.MobileNavigation{
    display: none;
}

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

Step 10: Make the navigation menu responsive

Ideally, you want to render the MobileNavigation component (which is currently invisible) to users with small-screen devices. To implement that, go to your NavBar.css and introduce a media query:

/*NavBar.css*/

@media (max-width: 600px){

    .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

For devices with a screen width of 600px and below, the media query above does the following:

  • Renders the MobileNavigation component

  • Hides the DesktopNavigation component

Resize your browser to confirm that it's active (the background color should change to red at the 600px breakpoint). You'll replace this color change effect with a hamburger icon in the next step.

Step 11: Add a hamburger icon

Remember the react-icons package you installed at the beginning of this tutorial? It's finally time to make use of it. The steps below explain how:

  1. Visit the react-icons website

  2. Enter the term "menu" into the search bar

  3. Scan the page to identify any hamburger icon you like

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

  5. Go to your MobileNavigation component and import the icon using the syntax below:

     //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 this new variable. Customize the icon with properties such as className, size, and color:

     //MobileNavigation.js
    
     const Hamburger = <MdOutlineMenu className="HamburgerMenu"
                size="30px" color="black"/>
    
  7. Lastly, render the Hamburger variable within the return statement of the MobileNavigation component:

     //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 12: Position the Hamburger Icon

You need to position the hamburger (or menu) icon to the extreme right of the browser. To implement that, locate the media query block in NavBar.css, and assign the following properties to the HamburgerMenu class name (assigned in step 11):

/*index.css*/

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

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

You should have a nice-looking hamburger icon rendered to your browser:

Step 13: Make the hamburger icon functional

For the hamburger icon to be functional, you'll attach an event listener to the icon. This event listener will call a function (that you'll create shortly) each time a user clicks on the icon. For now, 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 checking the browser’s console for the value you logged:

Logging a value to the console is cool, but the goal is to toggle the navigation menu on/off with each click on the icon. To implement that, import the useState hook into your MobileNavigation component:

//MobileNavigation.js 

import { useState } from "react";

With the useState hook imported, it's time to define a state and apply it in the JSX of the MobileNavigation component. The following steps will guide you:

  1. Define a state in the MobileNavigation component:

     //MobileNavigation.js 
    
     const [click, setclick] = useState(false);
    
     //the state above is initialized to "false"
    
  2. Within the onClick event, call setClick and pass "!click" to it as an argument. The idea is to use setClick to flip the state's value each time a 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.
    
  3. Specify a condition that will determine what to display and in what circumstance. You want React to display the NavLinks component (which contains the menu items) if the state’s value is true and to display nothing otherwise:

     //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 now toggles the navigation menu on and off when clicked.

Step 14: Add a "close" icon to MobileNavigation

In mobile view, users need a way of closing the menu items displayed by clicking the hamburger icon. To implement that, follow the steps below:

  1. Revisit the react-icons website

  2. Search for the term "close"

  3. Identify your preferred icon and click on it to copy its name

  4. Import the icon to your MobileNavigation component, just like 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 Hamburger's content and paste it into the new variable

  7. Edit the code by replacing MdOutlineMenu with MdClose:

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

     //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 15: Style the mobile navigation

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

  • Remove the background-color you assigned to the MobileNavigation and NavLinks className.

  • Assign the following properties to the ul:

      .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 value of top above is the same as the height value you assigned to the NavLinks class name in Step 6. That way, your mobile menu renders just below the navigation bar. See it in action below:

Tidying up

The project is almost complete, but there is one issue. The navigation menu does not go away when you select any of its items. To fix that, go through the steps below:

  1. Under the Close variable ( in the MobileNavigation component), define a function called "closeMenu." When called, this function will set the state's value to false.

     const closeMenu = () => setclick(false);
    
     /*
     1. The mobile navigation menu will go away
     when the state’s value is false.
    
     2. You need a way to trigger this closeMenu function 
     when a navigation item is selected.
    
  2. Down in the JSX, pass props to NavLinks:

     {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. Still within NavLinks, attach an onClick event to each of the list items and pass in both isCLicked and closeMenu props:

    ```javascript import './Navigation.css';

const NavLinks = ({isClicked, closeMenu}) => { return (

  • isClicked && closeMenu()}> HOME
  • isClicked && closeMenu()}> SERVICES
  • isClicked && closeMenu()}> ABOUT
  • isClicked && closeMenu()}> CONTACT
Call us on: (123) 456-78910 ); }

export default NavLinks; ```

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

Conclusion

This tutorial walked you through building a responsive hamburger menu in ReactJS. It may not be the only approach to navigation menus, but it's a good starting point for you as a beginner.

If you already know how to build responsive navigation menus with vanilla JavaScript, you should now compare that with what you saw in this React tutorial for a deeper level of understanding. In conclusion, adding responsive navigation to your projects is a practice you must embrace as a developer.