DEV Community

Cover image for Easy hamburger menu with JS - Beginners
ljc-dev
ljc-dev

Posted on • Updated on

Easy hamburger menu with JS - Beginners

A hamburger menu is a classic UI feature present in countless websites. It's used to show and hide a menu on click, especially used in mobile design.

In this tutorial, we'll learn to create a hamburger menu with HTML, CSS and Javascript.

result

Here's the HTML:

<head>
  <!-- Material Icon CDN -->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
</head>
<body>
  <ul class="menu">
    <li><a class="menuItem" href="#">Home</a></li>
    <li><a class="menuItem" href="#">Profile</a></li>
    <li><a class="menuItem" href="#">About</a></li>
    <li><a class="menuItem" href="#">Contacts</a></li>
  </ul>
  <button class="hamburger">
    <!-- material icons https://material.io/resources/icons/ -->
    <i class="menuIcon material-icons">menu</i>
    <i class="closeIcon material-icons">close</i>
  </button>
</body>
Enter fullscreen mode Exit fullscreen mode

Begin by adding a basic menu with a class of menu and menu links with a class of menuItem.

Then add a button with a class of hamburger and both a menu and a close icons inside of it. Later on we will hide the close icon by default with CSS and alternate which icon to show with Javascript.

You can use any icons family you want. I've used material icons by loading their CDN in the head and adding the menu and close icons inside of the button.

The menuIcon and closeIcon classes are used to reference the icons in CSS and Javascript later on.

Now let's add some CSS.

Add to the button position: fixed; so scrolling won't affect it. And z-index:100; to make sure it stays above every other element.

Add top and right with a value of 1rem to place it at the top-right corner of the screen.

.hamburger {
  position: fixed;
  z-index: 100;
  top: 1rem;
  right: 1rem;
  padding: 4px;
  border: black solid 1px;
  background: white;
  cursor: pointer;
}
Enter fullscreen mode Exit fullscreen mode

To hide the close icon by default, add display: none; to the closeIcon class.

.closeIcon {
  display: none;
}
Enter fullscreen mode Exit fullscreen mode

In the menu class, add position: fixed; so it can't be scrolled away.

Set the top, right, bottom and left to 0 to make the menu cover the whole screen.

.menu {
  position: fixed;
  transform: translateY(-100%);
  transition: transform 0.2s;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 99;
  background: black;
  color: white;
  list-style: none;
  padding-top: 4rem;
}
Enter fullscreen mode Exit fullscreen mode
  • transform: translateY(-100%); is used to hide the menu by default above the screen.

  • transition: transform 0.2s; is optional. It is used to animate the change in translation value to create a slide up/down effect.

By resetting translateY to 0, the menu will slide down and cover the whole screen.

Add it in a showMenu class:

.showMenu {
  transform: translateY(0);
}
Enter fullscreen mode Exit fullscreen mode

This class will be added and removed from the menu with Javascript to show and hide the menu.

Here's the Javascript for toggling the menu:

const menu = document.querySelector(".menu");
const menuItems = document.querySelectorAll(".menuItem");
const hamburger= document.querySelector(".hamburger");
const closeIcon= document.querySelector(".closeIcon");
const menuIcon = document.querySelector(".menuIcon");

function toggleMenu() {
  if (menu.classList.contains("showMenu")) {
    menu.classList.remove("showMenu");
    closeIcon.style.display = "none";
    menuIcon.style.display = "block";
  } else {
    menu.classList.add("showMenu");
    closeIcon.style.display = "block";
    menuIcon.style.display = "none";
  }
}

hamburger.addEventListener("click", toggleMenu);
Enter fullscreen mode Exit fullscreen mode

Clicking on the hamburger button will call toggleMenu().

It checks if the menu contains the class showMenu.

If the menu contains the showMenu class, we remove it to hide the menu. We also toggle the display to hide the close icon and show the menu icon.

If the menu doesn't have the showMenu class, we add it, show the close icon and hide the menu icon.

The hardest part is over! All that's left is to hide the menu when the user click on the links.

In the Javascript above, we got all the menu items with querySelectorAll.

const menuItems = document.querySelectorAll(".menuItem");
Enter fullscreen mode Exit fullscreen mode

With forEach, we can iterate through each link and add a call to toggleMenu().

toggleMenu() will in turn hide the menu (because if the user can click on the menu items it means that the menu is showing).

menuItems.forEach( 
  function(menuItem) { 
    menuItem.addEventListener("click", toggleMenu);
  }
)
Enter fullscreen mode Exit fullscreen mode

And that's it!

Thanks for reading 😄!!

(2nd rewrite 01/10/21)
I hope you've found it useful and happy coding 👨‍💻!

Oldest comments (23)

Collapse
 
studmuffin30 profile image
studmuffin30 • Edited

nice article,merci

Collapse
 
ljcdev profile image
ljc-dev

Thx Stud 😄, glad u like it!

Collapse
 
andresfjobs profile image
andresfjobs

great article man, I appreciated it a lot

Collapse
 
ljcdev profile image
ljc-dev

Thx a lot Andres, glad u found it useful 😁!!

Collapse
 
lathryx profile image
Lathryx

Hey! I can't get it working and I'm not really sure why.

The CSS properties are successfully being toggled because the button switches images correctly, and the event listeners are set up correctly because if I put a console.log statement in them that also works.

Does anybody know why?

Collapse
 
dzopunk profile image
dzopunk

I had the same problem.
I'm really not sure why. Tutorial is pretty straight forward.
My solution was creating new class with translateY(-100%) and transition property and adding it on .menu and toggle it in js.

I really wish someone replied to you sooner because I lost so much time 🤣

Collapse
 
lathryx profile image
Lathryx • Edited

testing bug with inline code.

Edit: Could not reproduce...

Collapse
 
ljcdev profile image
ljc-dev

Hey Lathryx, thx for checking my tutorial. I tried my best, but it isn't perfect 😄. If u want explanations on sth, u can find me on twitter 👌.

Collapse
 
ljcdev profile image
ljc-dev

Or ask here. But I meant I'm more present on twitter.

Collapse
 
ahmadullahnikzad profile image
ahmadullah

Thanks,
I want to create navigation drawer like dev.to's
Because when I click outside of the drawer it disappears.
Can anyone suggest me any solution.

Collapse
 
ljcdev profile image
ljc-dev

Thanks for reading Ahmadullah!! I've recreated this ham menu to make it similar to dev.to's.
codepen.io/ljc-dev/pen/zYoqbrN

Collapse
 
ahmadullahnikzad profile image
ahmadullah

Thanks a lot.
I was searching for this solution but I couldn't find it.
if you have any problem then let me know.
Thanks.

Thread Thread
 
ljcdev profile image
ljc-dev

U're welcome and thx for the offer 😉. I'm currently getting ready to start freelancing. Building projects and going to re design my portfolio 👌.

Collapse
 
saltybaguette profile image
Brian Gay

Any ideas on how to disable the menu from appearing out by default when navigating back to the page?

Collapse
 
ljcdev profile image
ljc-dev

Hello Brian, sorry about that delay. I've tried adding an about page and going to and back, the menu didn't stay open 🤔. If you are still having this trouble, I could have a look at your code 👌.

Collapse
 
nippermh profile image
Mark Hallam

Thanks for this. I just removed jquery and used the javascript to animate my hamburger icon. Sweet.

Collapse
 
ljcdev profile image
ljc-dev

You're welcome 😀!

Collapse
 
emjogale profile image
Emma

Thanks this was just what I was looking for! Great description 👍

Collapse
 
ljcdev profile image
ljc-dev

Glad it was of help Emma 😃!! I still found it lacking and rewrote it once again 😂.

Collapse
 
dzopunk profile image
dzopunk • Edited

It was really fun doing this tutorial, and thanks for great step by step explanation 🤠

Collapse
 
mihaigabriel1 profile image
mihai-gabriel1

Great work!

Collapse
 
keshri95 profile image
Ashish Keshri

amazing

Collapse
 
benjohnsonfullstack profile image
Ben Johnson

Thanks for the article! Saved me on a project that I was doing on my own a little ahead of my current knowledge. A quick note: I ended up using .replace instead of .add/.remove -- a little cleaner and particularly handy for wiping any CSS styles that you might want to completely hide/show when you trigger the toggle.
Image description

Thanks again! Huge help!