There are different ways to create an animated hamburger menu icon. For example, you can only use CSS or an SVG icon along with some JavaScript.

In this tutorial, we'll cover another method. That said, we'll grab such an icon from LottieFiles library and learn how to embed it into a responsive page header by taking advantage of Lottie Player.

Sound challenging?

What We’ll be Building

Without further intro, let’s check out what we’ll be building:

See the Pen Practicing Lottie Player: How to Embed an Animated Hamburger Menu Into a Web Page by George (@georgemarts) on CodePen.


Notice the hamburger and menu animations that happen each time you click on the hamburger icon.

Additionally, be sure to check the demo on a wide screen (>900px) to see how the menu layout changes.

1. Grab a Hamburger Menu

For this demonstration, we're going to use a hamburger icon created by Michael Foster.

The animated hamburger menu that we'll include into our page
The animated hamburger menu that we'll include into our page

This animation consists of 90 frames. The first 45 frames animate the icon up to its open state, while the last 45 ones animate it up to its close one. Keep an eye on these numbers as we'll use them later on.

2. Include the Lottie Player JavaScript Script

Coming up next, we’ll include the required Lottie Player JavaScript file in our project:

The required JavaScript file for Lottie Player
The required Lottie Player JavaScript file

3. Define the HTML Markup

Our page will consist of a header. Inside it, we'll place the following items:

  • The hamburger icon
  • The company logo
  • The navigation menu

Here's the associated markup:

<header class="page-header">
  <nav>
    <div class="page-header-inner">
      <a href="" class="toggle-menu" role="button" aria-controls="menu-wrapper" aria-label="Open navigation" aria-expanded="false">
        <lottie-player src="https://assets8.lottiefiles.com/packages/lf20_nzuitqg1.json"></lottie-player>
      </a>
      <a href="" class="logo">Bikes4U</a>
    </div>
    
    <div id="menu-wrapper" class="menu-wrapper">
      <ul>
        <li>
          <a href="">...</a>
        </li>
        ...
      </ul>
    </div>
  </nav>
</header>

Pay attention to the following:

  • To embed the hamburger icon, we'll add the lottie-player custom element and set its src property to the corresponding JSON file.
  • To make the hamburger icon clickable, we'll wrap it around a link that will have role="button". Normally, we would wrap it around a button element. However, as lottie-player emits divs, it's semantically incorrect to put a div inside a button.
  • To make the hamburger icon as accessible as possible, we'll use the aria-label, aria-expanded, and aria-controls ARIA attributes. As we'll discuss later, the values of the first two attributes will change depending on the menu state.

4. Define Some Basic Styles

As a next step, we'll define some reset styles. Nothing important.

So, to make the page a little more attractive, we'll add a custom Google Font to the project.

Also, we’ll define the no-transition class that will help us disable transitions on window resize. More on that in a bit.

Here are our reset styles:

:root {
  --white: white;
  --orange: #ffb128;
  --lightorange: #ffdf86;
}

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

ul {
  list-style: none;
}

a {
  text-decoration: none;
  color: inherit;
}

body {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  height: 100vh;
  font: 500 20px/1.2 "Montserrat", sans-serif;
  background: linear-gradient(var(--orange), var(--lightorange));
}

.no-transition {
  transition: none !important;
}

5. Specify the Main Styles

On screens wider than 900px, the header layout will look like this:

The header layout on wide screens
The header layout on wide screens

On narrow screens, the header layout will change to this:

The header layout on narrow screens
The header layout on narrow screens

Some key things to note:

  • The hamburger icon will have a width of 70px. Feel free to modify it according to your needs.
  • The menu will be hidden and appear with a slide-down animation.
  • To build the header layout, we'll make heavy use of flexbox and its alignment properties.

Here are all the header styles:

/*CUSTOM VARIABLES HERE*/

.page-header {
  position: fixed;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  padding: 40px 20px 0;
}

.page-header nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  max-width: 1200px;
  margin: 0 auto;
}

.page-header .page-header-inner {
  display: flex;
  align-items: center;
}

.page-header .page-header-inner * {
  z-index: 1;
}

.page-header .toggle-menu {
  margin-right: 10px;
  width: 70px;
}

.page-header lottie-player {
  display: flex;
}

.page-header .logo {
  font-weight: bold;
  font-size: 30px;
}

.page-header .menu-wrapper {
  transform: translateY(-200px);
  transition: transform 1s ease-in-out;
}

.page-header .menu-wrapper ul {
  display: flex;
  align-items: center;
}

.page-header .menu-wrapper li:not(:last-child) {
  margin-right: 35px;
}

.page-header .menu-wrapper a {
  display: inline-block;
  padding: 5px;
}

@media (max-width: 900px) {
  .page-header {
    padding-top: 20px;
  }

  .page-header .menu-wrapper {
    position: fixed;
    top: 0;
    left: 0;
    bottom: 0;
    right: 0;
    display: flex;
    transform: translateY(-100vh);
    overflow-y: auto;
    background: var(--orange);
  }

  .page-header .menu-wrapper ul {
    padding: 100px 0;
    margin: auto;
    flex-direction: column;
  }

  .page-header .menu-wrapper li:not(:last-child) {
    margin: 0 0 20px;
  }
}

6. Toggle the Menu

Each time we click on the menu link, the following actions will happen:

  • We'll toggle the menu-open class of the header. This will determine whether the menu will appear or not.
  • If the header contains the menu-open class, the hamburger icon should be animated up to its open state. To achieve this, we have to play frames between 0 and 45.
  • If the header doesn't contain the menu-open class, the hamburger icon should be animated back to its close state. To achieve this, we have two options. Either play frames between 46 and 90 or play frames between 45 and 0 (reverse the animation).
  • Depending on the menu state, we'll update the aria-label and aria-expanded ARIA attributes.

At this point, let me go through one tricky thing. As you might already know, Lottie Player is a wrapper of Lottie-web library. This library provides the playSegments() method that allows us to play specific frames. So, to get access to this method and be able to use it via the web player, we have first to call its getLottie() method.

With all the aforementioned in mind, here's the JavaScript code that implements this functionality:

const pageHeader = document.querySelector(".page-header");
const toggleMenu = document.querySelector(".toggle-menu");
const player = document.querySelector("lottie-player");
const menuWrapper = document.querySelector(".menu-wrapper");
const menuOpenedClass = "menu-open";

toggleMenu.addEventListener("click", function (e) {
  e.preventDefault();
  pageHeader.classList.toggle(menuOpenedClass);
  if (pageHeader.classList.contains(menuOpenedClass)) {
    this.setAttribute("aria-label", "Close navigation");
    this.setAttribute("aria-expanded", "true");
    player.getLottie().playSegments([0, 45], true);
  } else {
    this.setAttribute("aria-label", "Open navigation");
    this.setAttribute("aria-expanded", "false");
    player.getLottie().playSegments([45, 0], true);
    //player.getLottie().playSegments([46, 90], true);
  }
});

And the transition-related styles:

.page-header .menu-wrapper {
  transition: transform 1s ease-in-out;
}

.page-header.menu-open .menu-wrapper {
  transform: none;
}

Bonus: Clear Transitions on Resize

Our header is almost ready! There's one small optional, yet nice-to-have enhancement that we can do. That said, we'll stop the menu transitions on window resize. That's where the earlier defined no-transition class is needed.

Without going into more details, here's the JavaScript that handles this functionality:

...
const noTransitionClass = "no-transition";
let timer;

window.addEventListener("resize", function () {
  menuWrapper.classList.add(noTransitionClass);
  clearTimeout(timer);
  timer = setTimeout(function () {
    menuWrapper.classList.remove(noTransitionClass);
  }, 500);
});

If you want to understand what it does, just remove the code above and resize the window when the menu is hidden. You'll notice that the mobile menu instantly appears before hiding.

Conclusion

That's all, folks! Thanks to Lottie Player, we managed to incorporate an animated hamburger menu as a part of a fully responsive page header. Hopefully, this exercise helped you understand just one of the endless capabilities of Lottie animations and why they are becoming increasingly popular these days.

Let's remind ourselves what we built during this tutorial:

See the Pen Practicing Lottie Player: How to Embed an Animated Hamburger Menu Into a Web Page by George (@georgemarts) on CodePen.


Go ahead, fork this demo and customize it in line with your expectations! Even better, enhance a web page with the techniques you learned today and show us the result!

Thanks for reading!