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](https://paper-attachments.dropbox.com/s_2A8140245FC1BF87B611CBA18620CF5C58424B4E48EB2CCD6A0F6EF2CAE7166D_1612097532252_michael_foster_lottie_hamburger.png)
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](https://paper-attachments.dropbox.com/s_2A8140245FC1BF87B611CBA18620CF5C58424B4E48EB2CCD6A0F6EF2CAE7166D_1612097620357_lottie_player_javascript_file.png)
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 itssrc
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 abutton
element. However, aslottie-player
emitsdiv
s, it's semantically incorrect to put adiv
inside abutton
. - To make the hamburger icon as accessible as possible, we'll use the
aria-label
,aria-expanded
, andaria-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](https://paper-attachments.dropbox.com/s_2A8140245FC1BF87B611CBA18620CF5C58424B4E48EB2CCD6A0F6EF2CAE7166D_1612097658420_header_layout_desktop.jpg)
On narrow screens, the header layout will change to this:
![The header layout on narrow screens](https://paper-attachments.dropbox.com/s_2A8140245FC1BF87B611CBA18620CF5C58424B4E48EB2CCD6A0F6EF2CAE7166D_1612097664491_header_layout_mobile.jpg)
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
andaria-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!