Animated Hamburger Side Menu 🍔

— 14 minute read

Sorry, this blog post is not about making the perfect burger, I know disappointing right?

Instead, we will be looking into a CSS Animated Side Menu.

I've created this menu for my current company and wanted to guide you through some of the processes, this is a simplified version. You will learn how to animate the hamburger icon and how to slide in the menu from the right side. We will also implement two views, one for desktop and one for mobile views.

This is my interpretation and fix for this setup; there are many, many ways of doing this!

HTML Structure for side menu permalink

<nav id="main-nav" class="nav">
<a href="#" class="logo">
<img width="50" src="https://daily-dev-tips.com/images/logo.png" />
</a>
<div class="nav-menu">
<span class="nav-menu-item"> Menu</span>
<span class="nav-menu-cross"></span>
</div>
<div class="nav-menu-side">
<nav class="nav-menu-side-nav">
<ul>
<li><a href="#">Home.</a></li>
<li><a href="#">Work.</a></li>
<li><a href="#">Blog.</a></li>
<li><a href="#">Resume.</a></li>
<li><a href="#">Contact.</a></li>
</ul>
</nav>
</div>
</nav>

As you can see we use one main nav to wrap the whole menu bar and side menu in. The menu has three child elements which are:

  • logo with link to home
  • nav menu which contains the hamburger 🍔
  • side menu with all the links

The HTML doesn't contain any special hacks so let's dive into the CSS part.

JavaScript to add a open class permalink

So as far as JavaScript goes in this example, we don't need much, we just want to add one class to our most top element once we click our menu button or hamburger menu.

var mainNav = document.getElementById('main-nav');
document.addEventListener('click', function(event) {
if (!event.target.matches('.nav-menu')) return;
mainNav.classList.toggle('nav-open');
});

So we get our main navigation element, and add a click listener. If that is our nav-menu class we will toggle the nav-open class on it. Read more about JavaScript classList.

CSS Animated Hamburger Menu permalink

body {
background: #fff;
min-height: 100vh;
}

We make the body background white and add a min-height of 100vh to make it full screen. Read more about viewport units.

.logo {
display: flex;
margin-left: 24px;
}

For the logo we say it must display: flex to fix a spacing issue and have a margin-left of 24px to offset if from the side. (We can't use padding on the navbar because it will become too wide)

.nav {
position: fixed;
width: 100%;
z-index: 100;
transition: all 0.25s;
display: flex;
justify-content: space-between;
padding: 24px 0px;
}

The nav is the actual main container for this project, we make it fixed so it will be sticked to the top if you had more content. Then we give it a z-index so it will lay on top of other content. transition is the animation effect and we add it to all effects. Then we use display: flex and justify-content: space-between to put the logo left and the menu right. And we add 24px padding to the top and bottom.

.nav:after {
content: '';
position: absolute;
height: 1px;
width: 95%;
bottom: 0;
left: 2.5%;
background: #000;
}

Here we have another pseudo-element like we learned in the article CSS pseudo-elements. This code i'll add a 1px high line which is 95% of our viewport and it will show black. We use this as the divider line for the menu.

.nav-open {
color: #fff;
}

Nav-open will be our class that will make the menu open, so once it's open we make the text white instead of black.

.nav-open:after {
background: #fff;
}

We then also make the divider line white instead of black.

.nav-menu {
cursor: pointer;
display: flex;
align-items: center;
padding-right: 34px;
position: relative;
margin-right: 24px;
}
.nav-menu > * {
pointer-events: none;
}

This is the CSS for the menu text, it makes sure the text is in the middle of the bar and we add margin-right: 24px to offset it. Then we make sure all children have no pointer-events with pointer-events: none this is important for our JavaScript code. It makes sure it only fires on the parent element.

The Hamburg CSS Setup permalink

Many of you will wonder how we can setup the cross. So let's go through that CSS.

.nav-menu-cross {
position: absolute;
top: 20.5px;
right: 0;
height: 2px;
width: 20px;
background-color: #000;
display: block;
border-radius: 5px;
transition: transform 0.25s, -webkit-transform 0.25s;
}

With this we create a small line and say it can animate with the transition rule. As you can see it's important to position: absolute it.

But with this we only have one line, so let's use another CSS Pseudo-element after.

.nav-menu-cross:before {
content: '';
display: block;
position: absolute;
height: 2px;
width: 20px;
background-color: #000;
top: 5px;
right: 0;
border-radius: 5px;
transition: transform 0.25s, -webkit-transform 0.25s;
}

As you can see it's a copy of the above one, but 5px below the first one.

Going from the Hamburger to the Cross permalink

So once we click the menu button we want to see the Hamburger 🍔 turn into a Cross ❌.

.nav-open .nav-menu-cross {
background: #fff;
transform: translate3d(0, 4px, 0) rotate(45deg);
}
.nav-open .nav-menu-cross:before {
background: #fff;
transform: rotate(-90deg) translate3d(5px, 0px, 0);
}

So, if the main navigation has the nav-open class which we added with our JavaScript we tell our hamburger menu to turn white and use transform to rotate our sticks to look like a cross! Amazingly simply right?!

The actual side menu permalink

.nav-menu-side {
transition: all 0.25s;
position: absolute;
left: 100%;
width: 100%;
height: 100vh;
padding-top: 98px;
top: 0px;
z-index: -1;
background: #000;
}

This is our actual side menu we position it absolute and make sure its set to left: 100% this makes it start outside the viewport.

So image your browser [browser] and next to it [nav-menu-side] so it's not visible at first. We then add padding-top: 98px to make it only start under the menu bar.

.nav-menu-side-nav {
margin-top: 36px;
display: flex;
justify-content: center;
text-aling: center;
width: 100%;
}
.nav-menu-side-nav ul {
list-style: none;
text-align: center;
}
.nav-menu-side-nav ul li {
padding-bottom: 12px;
}
.nav-menu-side-nav ul li a {
color: #fff;
text-decoration: none;
cursor: pointer;
}

All this is basically the styling for the menu, we make sure it's centered inside and do some basic CSS to make it look pretty.

Showing the open Side Menu permalink

So what happens to the side menu if the nav-open class is on our main navigation element.

.nav-open .nav-menu-side {
left: 47%;
}
.nav-open .nav-menu-side-nav {
width: 53%;
}

This code will fire and make the side menu have a left of 47%. Remember we added transition: all 0.25s; to our side menu, that will make sure this slides in! Then we fix the position of the navigation inside our side menu width a percentage based width.

@media screen and (max-width: 1024px) {
.nav-open .nav-menu-side {
left: 0%;
}
.nav-open .nav-menu-side-nav {
width: 100%;
}
}

The code above is for screens smaller then 1024px we call these media-queries and they can be used in many varieties. In this case we just want the side menu to be completely on the left of our page and our navigation inside full width.

Demo hamburger side menu permalink

A lot of code, but it really wanted to show a nice solution, I would strongly suggest you try this yourself or have a play on this Codepen.

See the Pen Animated Hamburger Side Menu 🍔 by Chris Bongers (@rebelchris) on CodePen.

Thank you for reading, and let's connect! permalink

Thank you for reading my blog. Feel free to subscribe to my email newsletter and connect on Facebook or Twitter