How to create an animated hamburger menu
Tags: webdev, javascript, tutorial, programming
Published: 2024-03-08 15:45:53

In today's fast-paced digital world, capturing user attention is crucial. A well-designed website not only looks good but also provides a seamless user experience. One way to achieve this is by incorporating interactive elements, like an animated hamburger menu.

## What is a hamburger menu?

A hamburger menu, also known as a three-line menu, is a popular navigation icon commonly used on websites, especially on mobile devices. It consists of three horizontal lines stacked on top of each other, resembling a hamburger patty. When clicked, it expands to reveal the website's navigation links.

## Why animate your hamburger menu?

Static hamburger menus can sometimes appear bland and uninviting. Adding an animation can bring your menu to life, making it more visually appealing and engaging for users. This can lead to:

- **Increased user interaction:** A dynamic menu can spark curiosity and encourage users to explore your website's navigation.

- **Enhanced user experience:** A smooth and visually pleasing animation can elevate the overall user experience on your website.

- **Improved brand identity:** A unique and creative animation can contribute to your website's brand personality and leave a lasting impression on visitors.

## Creating an animated hamburger menu with CSS

create an index.html file
```HTML
<!DOCTYPE html>

<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Animated Hamburger Menu</title>
  <link rel="stylesheet" href="./css/style.css" />
</head>

<body class="flex">
  <div class="frame flex">
    <div class="hamburger">
      <div class="hamburger__animated hamburger--before"></div>
      <div class="hamburger__animated"></div>
      <div class="hamburger__animated hamburger--after"></div>
    </div>
  </div>
  <script src="./js/script.js"></script>
</body>

</html>
```

**Hamburger Menu Styling:** The `.hamburger` class styles the overall hamburger menu element, including its position, height, width, cursor, and hover effect.

```CSS
.hamburger {
  position: relative;
  height: 40px;
  width: 80px;
  cursor: pointer;
}
```

**Animated Lines:** The `.hamburger__animated` class styles the three lines of the hamburger menu. It defines their position, width, height, background color, transition properties, and border-radius. The `.hamburger--before` and `.hamburger--after` classes target the top and bottom lines of the menu, respectively.

```CSS
.hamburger__animated {
  position: absolute;
  width: 80px;
  height: 8px;
  background: #fff;
  transition: all ease-in-out 0.2s;
  top: 2rem;
  border-radius: 10px;
  box-shadow: 1px 2px 3px rgba(0, 0, 0, 0.2);
}

.hamburger--before {
  top: 0rem;
}

.hamburger--after {
  top: 1rem;
}
```

**Hover Animation:** The hover state of the `.hamburger` element triggers various animation effects on the lines using additional classes like `.hamburger__animated--top`, `.hamburger__animated--before-rotate`, etc. These classes modify properties like top, transform, visibility, and width to create the animation.

```CSS
.hamburger:hover
.hamburger__animated:not(.hamburger--before, .hamburger--after) {
  width: 60px;
}

.hamburger:hover .hamburger--after {
  width: 70px;
}

.hamburger__animated--top {
  top: 0.5rem;
}

.hamburger__animated--before-rotate {
  transform: rotate(45deg);
  transition-delay: 0.2s;
}
.hamburger__animated--rotate {
  transform: rotate(-45deg);
  transition-delay: 0.2s;
}

.hamburger__animated--transparent {
  visibility: hidden;
}

.hamburger__animated--width {
  width: 80px !important;
}
```

Added a little more CSS to make it look awesome

```CSS
.flex {
  display: flex;
  justify-content: center;
  align-items: center;
}

body {
  background: #8a50f8;
  height: 100vh;
  margin: 0;
}

.frame {
  height: 400px;
  width: 400px;
  border-radius: 20px;
  background: linear-gradient(145deg, #9456ff, #7c48df);
  box-shadow: 13px 13px 22px #7946da, -13px -13px 22px #9b5aff;
}
```


Here is the full CSS code.
```CSS
/* General style */
.flex {
  display: flex;
  justify-content: center;
  align-items: center;
}

body {
  background: #8a50f8;
  height: 100vh;
  margin: 0;
}

.frame {
  height: 400px;
  width: 400px;
  border-radius: 20px;
  background: linear-gradient(145deg, #9456ff, #7c48df);
  box-shadow: 13px 13px 22px #7946da, -13px -13px 22px #9b5aff;
}

.hamburger {
  position: relative;
  height: 40px;
  width: 80px;
  cursor: pointer;
}

.hamburger__animated {
  position: absolute;
  width: 80px;
  height: 8px;
  background: #fff;
  transition: all ease-in-out 0.2s;
  top: 2rem;
  border-radius: 10px;
  box-shadow: 1px 2px 3px rgba(0, 0, 0, 0.2);
}

.hamburger--before {
  top: 0rem;
}

.hamburger--after {
  top: 1rem;
}
.hamburger:hover
.hamburger__animated:not(.hamburger--before, .hamburger--after) {
  width: 60px;
}

.hamburger:hover .hamburger--after {
  width: 70px;
}

.hamburger__animated--top {
  top: 0.5rem;
}

.hamburger__animated--before-rotate {
  transform: rotate(45deg);
  transition-delay: 0.2s;
}
.hamburger__animated--rotate {
  transform: rotate(-45deg);
  transition-delay: 0.2s;
}

.hamburger__animated--transparent {
  visibility: hidden;
}

.hamburger__animated--width {
  width: 80px !important;
}

```

Here is the full JavaScript code.
```JS
const hamburger = document.querySelector(".hamburger");
const burger = document.querySelectorAll(".hamburger__animated");

/*
* Initializes a boolean variable named 
* showMenu to false,  indicating that 
* the menu is initially hidden.
**/
 let showMenu = false;

/**
 * a function named rotate that 
 * handles the animation of the 
 * hamburger menu icon
**/
const rotate = () => {
  for (i = 0; i < burger.length; i++)
    burger[0].classList.add("hamburger__animated--transparent");
  burger[1].classList.add("hamburger__animated--rotate");
  burger[2].classList.add("hamburger__animated--before-rotate");
};

/*
 * The function body uses an 
 * `if...else` statement to 
 * handle two scenarios: showing 
 * and hiding the menu.
**/
const toggleMenu = () => {
  if (!showMenu) {
    for (let i = 0; i < burger.length; i++) {
      burger[i].classList.add("hamburger__animated--width");
      burger[i].classList.add("hamburger__animated--top");
    }
    setTimeout(rotate, 0);
    showMenu = true;
  } else {
    for (i = 1; i < burger.length; i++)
      burger[1].classList.remove("hamburger__animated--rotate");
    burger[2].classList.remove("hamburger__animated--before-rotate");

    const rotate = () => {
      for (let i = 0; i < burger.length; i++) {
        burger[i].classList.remove(
          "hamburger__animated--top",
          "hamburger__animated--transparent",
          "hamburger__animated--width"
        );
      }
    };
    setTimeout(rotate, 200);

    showMenu = false;
  }
};
hamburger.addEventListener("click", toggleMenu);

```
{% codepen https://codepen.io/codeauthor1/pen/qBxXpbq %}