DEV Community

William Baker
William Baker

Posted on

Building Animated Hamburger Menus with hamburger-react in React

hamburger-react is a lightweight React library for creating animated hamburger menu icons with multiple animation styles. It provides a simple API for toggling between hamburger and close (X) states with smooth animations, perfect for navigation menus and mobile interfaces. This guide walks through setting up and creating animated hamburger menus using hamburger-react with React, from installation to a working implementation. This is part 41 of a series on using hamburger-react with React.

Prerequisites

Before you begin, make sure you have:

  • Node.js version 14.0 or higher installed
  • npm, yarn, or pnpm package manager
  • A React project (version 16.8 or higher) or create-react-app setup
  • Basic knowledge of React hooks (useState)
  • Familiarity with JavaScript/TypeScript
  • Understanding of CSS for styling

Installation

Install hamburger-react using your preferred package manager:

npm install hamburger-react
Enter fullscreen mode Exit fullscreen mode

Or with yarn:

yarn add hamburger-react
Enter fullscreen mode Exit fullscreen mode

Or with pnpm:

pnpm add hamburger-react
Enter fullscreen mode Exit fullscreen mode

After installation, your package.json should include:

{
  "dependencies": {
    "hamburger-react": "^2.5.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

hamburger-react requires no additional setup. You can start using it immediately after installation.

First Example / Basic Usage

Let's create a simple hamburger menu component. Create a new file src/HamburgerExample.jsx:

// src/HamburgerExample.jsx
import React, { useState } from 'react';
import { Hamburger } from 'hamburger-react';

function HamburgerExample() {
  const [isOpen, setOpen] = useState(false);

  return (
    <div style={{ padding: '20px' }}>
      <h2>Hamburger Menu Example</h2>
      <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
        <Hamburger toggled={isOpen} toggle={setOpen} />
        <span>{isOpen ? 'Menu is open' : 'Menu is closed'}</span>
      </div>
    </div>
  );
}

export default HamburgerExample;
Enter fullscreen mode Exit fullscreen mode

Update your App.jsx:

// src/App.jsx
import React from 'react';
import HamburgerExample from './HamburgerExample';
import './App.css';

function App() {
  return (
    <div className="App">
      <HamburgerExample />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This creates a basic hamburger icon that toggles between hamburger and close (X) states when clicked.

Understanding the Basics

hamburger-react provides several key features:

  • Hamburger component: The main component that renders the animated icon
  • toggled prop: Controls whether the hamburger is in the open (X) or closed (hamburger) state
  • toggle prop: Function to update the toggled state
  • Animation styles: Multiple built-in animation styles
  • Customization: Size, color, and other styling options

Key concepts:

  • Controlled Component: The hamburger is a controlled component - you manage its state
  • State Management: Use useState to track whether the menu is open or closed
  • Toggle Function: Pass a state setter function to the toggle prop
  • Animation Styles: Choose from different animation styles like 'spin', 'squeeze', 'rotate', etc.
  • Styling: Customize size, color, and other visual properties

Here's an example with different animation styles:

// src/AnimationStylesExample.jsx
import React, { useState } from 'react';
import { Hamburger } from 'hamburger-react';

function AnimationStylesExample() {
  const [isOpen1, setOpen1] = useState(false);
  const [isOpen2, setOpen2] = useState(false);
  const [isOpen3, setOpen3] = useState(false);

  return (
    <div style={{ padding: '20px' }}>
      <h2>Different Animation Styles</h2>
      <div style={{ display: 'flex', flexDirection: 'column', gap: '20px', marginTop: '20px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
          <Hamburger toggled={isOpen1} toggle={setOpen1} />
          <span>Default style</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
          <Hamburger toggled={isOpen2} toggle={setOpen2} size={30} />
          <span>Larger size</span>
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
          <Hamburger toggled={isOpen3} toggle={setOpen3} color="#007bff" />
          <span>Custom color</span>
        </div>
      </div>
    </div>
  );
}

export default AnimationStylesExample;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a navigation menu with a hamburger icon:

// src/NavigationMenu.jsx
import React, { useState } from 'react';
import { Hamburger } from 'hamburger-react';

function NavigationMenu() {
  const [isOpen, setOpen] = useState(false);

  const menuItems = [
    { id: 1, label: 'Home', href: '#home' },
    { id: 2, label: 'About', href: '#about' },
    { id: 3, label: 'Services', href: '#services' },
    { id: 4, label: 'Contact', href: '#contact' }
  ];

  return (
    <nav style={{
      backgroundColor: '#333',
      padding: '10px 20px',
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      position: 'relative'
    }}>
      <div style={{ color: 'white', fontSize: '20px', fontWeight: 'bold' }}>
        Logo
      </div>

      {/* Desktop Menu */}
      <div style={{
        display: window.innerWidth > 768 ? 'flex' : 'none',
        gap: '20px'
      }}>
        {menuItems.map(item => (
          <a
            key={item.id}
            href={item.href}
            style={{
              color: 'white',
              textDecoration: 'none',
              padding: '5px 10px'
            }}
          >
            {item.label}
          </a>
        ))}
      </div>

      {/* Mobile Hamburger */}
      <div style={{
        display: window.innerWidth <= 768 ? 'block' : 'none'
      }}>
        <Hamburger
          toggled={isOpen}
          toggle={setOpen}
          size={24}
          color="white"
        />
      </div>

      {/* Mobile Menu */}
      {isOpen && (
        <div style={{
          position: 'absolute',
          top: '100%',
          left: 0,
          right: 0,
          backgroundColor: '#333',
          padding: '20px',
          display: 'flex',
          flexDirection: 'column',
          gap: '10px',
          zIndex: 1000
        }}>
          {menuItems.map(item => (
            <a
              key={item.id}
              href={item.href}
              onClick={() => setOpen(false)}
              style={{
                color: 'white',
                textDecoration: 'none',
                padding: '10px',
                borderBottom: '1px solid #555'
              }}
            >
              {item.label}
            </a>
          ))}
        </div>
      )}
    </nav>
  );
}

export default NavigationMenu;
Enter fullscreen mode Exit fullscreen mode

Now create a more advanced responsive navigation component:

// src/ResponsiveNavigation.jsx
import React, { useState, useEffect } from 'react';
import { Hamburger } from 'hamburger-react';

function ResponsiveNavigation() {
  const [isOpen, setOpen] = useState(false);
  const [isMobile, setIsMobile] = useState(window.innerWidth <= 768);

  useEffect(() => {
    const handleResize = () => {
      setIsMobile(window.innerWidth <= 768);
      if (window.innerWidth > 768) {
        setOpen(false);
      }
    };

    window.addEventListener('resize', handleResize);
    return () => window.removeEventListener('resize', handleResize);
  }, []);

  const menuItems = [
    { id: 1, label: 'Home', href: '#home' },
    { id: 2, label: 'About', href: '#about' },
    { id: 3, label: 'Services', href: '#services' },
    { id: 4, label: 'Portfolio', href: '#portfolio' },
    { id: 5, label: 'Contact', href: '#contact' }
  ];

  return (
    <nav style={{
      backgroundColor: '#2c3e50',
      padding: '15px 30px',
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      position: 'sticky',
      top: 0,
      zIndex: 1000,
      boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
    }}>
      <div style={{
        color: 'white',
        fontSize: '24px',
        fontWeight: 'bold',
        letterSpacing: '1px'
      }}>
        MyApp
      </div>

      {/* Desktop Menu */}
      {!isMobile && (
        <div style={{
          display: 'flex',
          gap: '30px',
          alignItems: 'center'
        }}>
          {menuItems.map(item => (
            <a
              key={item.id}
              href={item.href}
              style={{
                color: 'white',
                textDecoration: 'none',
                padding: '8px 15px',
                borderRadius: '4px',
                transition: 'background-color 0.3s'
              }}
              onMouseEnter={(e) => e.target.style.backgroundColor = '#34495e'}
              onMouseLeave={(e) => e.target.style.backgroundColor = 'transparent'}
            >
              {item.label}
            </a>
          ))}
        </div>
      )}

      {/* Mobile Hamburger */}
      {isMobile && (
        <div>
          <Hamburger
            toggled={isOpen}
            toggle={setOpen}
            size={28}
            color="white"
            rounded
          />
        </div>
      )}

      {/* Mobile Menu Overlay */}
      {isMobile && isOpen && (
        <>
          <div
            style={{
              position: 'fixed',
              top: 0,
              left: 0,
              right: 0,
              bottom: 0,
              backgroundColor: 'rgba(0, 0, 0, 0.5)',
              zIndex: 999
            }}
            onClick={() => setOpen(false)}
          />
          <div style={{
            position: 'fixed',
            top: 0,
            right: 0,
            width: '280px',
            height: '100vh',
            backgroundColor: '#2c3e50',
            padding: '20px',
            display: 'flex',
            flexDirection: 'column',
            gap: '10px',
            zIndex: 1000,
            boxShadow: '-2px 0 10px rgba(0,0,0,0.3)',
            transform: isOpen ? 'translateX(0)' : 'translateX(100%)',
            transition: 'transform 0.3s ease-in-out'
          }}>
            <div style={{
              display: 'flex',
              justifyContent: 'space-between',
              alignItems: 'center',
              marginBottom: '20px',
              paddingBottom: '20px',
              borderBottom: '1px solid #34495e'
            }}>
              <div style={{ color: 'white', fontSize: '20px', fontWeight: 'bold' }}>
                Menu
              </div>
              <Hamburger
                toggled={isOpen}
                toggle={setOpen}
                size={24}
                color="white"
              />
            </div>
            {menuItems.map(item => (
              <a
                key={item.id}
                href={item.href}
                onClick={() => setOpen(false)}
                style={{
                  color: 'white',
                  textDecoration: 'none',
                  padding: '15px',
                  borderRadius: '4px',
                  transition: 'background-color 0.3s'
                }}
                onMouseEnter={(e) => e.target.style.backgroundColor = '#34495e'}
                onMouseLeave={(e) => e.target.style.backgroundColor = 'transparent'}
              >
                {item.label}
              </a>
            ))}
          </div>
        </>
      )}
    </nav>
  );
}

export default ResponsiveNavigation;
Enter fullscreen mode Exit fullscreen mode

Update your App.jsx:

// src/App.jsx
import React from 'react';
import ResponsiveNavigation from './ResponsiveNavigation';
import './App.css';

function App() {
  return (
    <div className="App">
      <ResponsiveNavigation />
      <div style={{ padding: '40px' }}>
        <h1>Welcome to My App</h1>
        <p>This is the main content area. Resize your browser to see the responsive navigation menu.</p>
      </div>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This example demonstrates:

  • Responsive navigation menu
  • Hamburger icon for mobile devices
  • Slide-in menu panel
  • Overlay background
  • Smooth animations
  • State management for menu open/close

Common Issues / Troubleshooting

  1. Hamburger not animating: Make sure you're using the toggled and toggle props correctly. The toggled prop should be a boolean state, and toggle should be a function that updates that state.

  2. Menu not closing: Ensure you're updating the state when menu items are clicked. Call setOpen(false) in the onClick handler of menu items.

  3. Styling conflicts: If the hamburger doesn't look right, check for CSS conflicts. You can customize the appearance using the size, color, and rounded props.

  4. Mobile menu not showing: Check that you're conditionally rendering the mobile menu based on screen size. Use window.innerWidth or CSS media queries to detect mobile devices.

  5. Animation not smooth: hamburger-react handles animations automatically. If animations seem choppy, check for performance issues or CSS conflicts that might be affecting the component.

  6. State not updating: Make sure you're using useState correctly and passing the state setter function to the toggle prop, not calling it directly.

Next Steps

Now that you have an understanding of hamburger-react:

  • Explore different animation styles and customization options
  • Learn about accessibility features for hamburger menus
  • Implement keyboard navigation for menu items
  • Add animations to the menu panel
  • Integrate with React Router for navigation
  • Learn about other menu libraries (react-burger-menu, react-sidebar)
  • Check the official repository: https://github.com/luukdv/hamburger-react
  • Look for part 42 of this series for more advanced topics

Summary

You've successfully set up hamburger-react in your React application and created a responsive navigation menu with an animated hamburger icon. hamburger-react provides a simple, elegant solution for creating hamburger menu icons with smooth animations.

SEO Keywords

hamburger-react
React hamburger menu
hamburger-react tutorial
React animated menu icon
hamburger-react installation
React mobile navigation
hamburger-react example
React responsive menu
hamburger-react setup
React menu toggle
hamburger-react customization
React navigation component
hamburger-react animations
React mobile menu
hamburger-react getting started

Top comments (0)