3 Steps Simple Responsive Hamburger Menu In Pure CSS

Welcome to a tutorial on how to create a simple responsive pure CSS Hamburger Menu. Yep, there are plenty of other hamburger menus on the Internet, but some of them still require the use of Javascript. So here it is, a menu that is purely CSS-driven, not a single line of Javascript. Read on to find out how to build one!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

TABLE OF CONTENTS

Download & Demo How to Build Useful Bits
Tutorial Video The End

 

 

DOWNLOAD & DEMO

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download the source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

HAMBURGER MENU DEMO

Go ahead. Resize the window and see the hamburger menu in action.

 

 

HOW TO BUILD A HAMBURGER MENU

Building a hamburger menu is actually not that difficult these days with the help of modern CSS…

 

STEP 1) THE HTML

index.html
<!-- (A) MENU WRAPPER -->
<nav id="hamnav">
  <!-- (B) THE HAMBURGER -->
  <label for="hamburger">&#9776;</label>
  <input type="checkbox" id="hamburger"/>
 
  <!-- (C) MENU ITEMS -->
  <div id="hamitems">
    <a href="a.html">First</a>
    <a href="b.html">Second</a>
    <a href="c.html">Third</a>
    <a href="d.html">Forth</a>
  </div>
</nav>

The HTML part should be pretty straightforward:

  1. First, we create the wrapper for the navigation menu <nav id="hamnav">.
  2. Followed by using a <label for="hamburger"> and <input type="checkbox" id="hamburger"/> as the hamburger button. For people who are new, that &#9776; is the HTML symbol for the “3 lines hamburger icon”.
  3. Finally, we sandwich the menu items <a> inside the  <div id="hamitems"> wrapper.

That’s all, zero Javascript involved.

 

 

STEP 2) CSS FOR BIG SCREENS

ham-menu.css
/* [ON BIG SCREEN] */
/* (A) WRAPPER */
#hamnav {
  width: 100%;
  background: #000;
}

/* (B) HORIZONTAL MENU ITEMS */
#hamitems { display: flex; }
#hamitems a {
  flex-grow: 1;
  flex-basis: 0;
  padding: 10px;
  color: white;
  text-decoration: none;
  text-align: center;
}
#hamitems a:hover { background: #af0d0d; }

/* (C) HIDE HAMBURGER */
#hamnav label, #hamburger { display: none; }

The CSS is where all the magic happens. This may seem to be a little complicated, but let’s take it step-by-step. Starting with how to display a “normal menu bar” on the big screens:

  1. Self-explanatory, a full-width navigation menu.
  2. Next, we set #hamitems to display: flex. Adding flex-grow: 1 and flex-basis: 0 to the menu items will automatically space them out equally.
  3. Since we do not need the hamburger icon on the big screen, we hide it by attaching display: none to #hamnav label and #hamburger.

This is actually all the important mechanics on the big screen, and we now have a working horizontal navigation bar.

 

 

STEP 3) RESPONSIVE CSS FOR SMALL SCREENS

ham-menu.css
/* [ON SMALL SCREENS] */
@media screen and (max-width: 768px){
  /* (A) BREAK INTO VERTICAL MENU */
  #hamitems a {
    box-sizing: border-box;
    display: block;
    width: 100%;
    border-top: 1px solid #333;
  }
 
  /* (B) SHOW HAMBURGER ICON */
  #hamnav label { 
    display: inline-block; 
    color: white;
    background: #a02620;
    font-style: normal;
    font-size: 1.2em;
    padding: 10px;
  }

  /* (C) TOGGLE SHOW/HIDE MENU */
  #hamitems { display: none; }
  #hamnav input:checked ~ #hamitems { display: block; }
}

Lastly, we add some style changes on the small screen to do the responsive magic:

  1. Transform the horizontal menu into a vertical one by adding #hamitems a { width: 100% }
  2. Show the hamburger icon with #hamnav label { display: inline-block }.
    • Take extra note – We are showing the hamburger label only, the checkbox remains hidden.
    • The checkbox will still work when the user clicks on the label.
  3. A little confusing, but this is where the magic happens.
    • By default, #hamitems { display: none; } will hide the menu items.
    • #hamnav input:checked ~ #hamitems { display: block; } in simple English – Show the menu items when the hidden checkbox is checked.

 

 

USEFUL BITS & LINKS

That’s it for the code, and here is a small extra that you may find useful.

 

STICKY MENU BAR

Want the menu bar to be permanently fixed on top of the screen as the user scrolls down on your website? Simply add a position: sticky to the navigation bar, and that should do the magic.

theme.css
#hamnav {
  position: sticky;
  top: 0;
}

But this will probably cause more problems on a small screen, so use it wisely.

 

BIGGER HAMBURGER?

The hamburger icon is an HTML symbol. Yes, changing the size is as easy as setting label[for="hamburger"] { font-size: XX em }.

 

I WANT DROPDOWN ITEMS!

That won’t be “simple” anymore, but feel free to challenge yourself…

 

COMPATIBILITY CHECKS

This hamburger menu works nice across all modern browsers.

 

TUTORIAL VIDEO

 

INFOGRAPHIC CHEAT SHEET

Pure CSS Hamburger Menu (click to enlarge)

 

THE END

Thank you for reading, and we have come to the end of this tutorial. I hope that it has helped you to create a better menu system for your project, and if you have anything to add to this guide, please feel free to comment below. Good luck and happy coding!

37 thoughts on “3 Steps Simple Responsive Hamburger Menu In Pure CSS”

  1. Hello there! Thank you so much for your tutorial. I really enjoyed it and the result is very good and responsive. I just have one problem with it: on a small screen the menu remains open when I click on the links (I’m using it in a one-page site with anchor links). What would the best method be to close it on click of the menu items?

    Sorry for the (very probably) stupid question, I’m a newbie, and any insight would be greatly appreciated.

    Thank you!!

  2. Love the simplicity of this! And your clear instructions, great for a newbie. Only one question; what if you’d like to have the burger icon on the right side? Can’t figure out how to do that…any hints please? 😉

    Ok figured it out now. But placing the menu inside a css grid container causes the whole header to expand down when opening the menu, how can I make it expand over/on top of the page/content?

    1. 1) #hamnav label { position: absolute; right: 0; }

      2) A “floating menu” is not a good design here. Consider the case of a small screen in landscape orientation. When the menu is longer than the page content itself, it gets cut off outside the screen area. More fixes need to be done with awkward scroll bars and empty spaces.

  3. Christopher Walker

    Thank you this is pure genius. I was really wondering how it would work with the checkbox hidden, but I guess even with display set to none for the checkbox, clicking the label will still toggle its checked state, huh? Very cool. As much as I like coding in javascript, if the same functionality can be achieved with pure HTML and CSS I’m always for that. 😉

  4. Hi,
    I am having a problem with this code – it works on my desktop when I resize but when I look at it on my mobile device (Samsung Galaxy S9 and Galaxy tab 7 ) it doesn’t work? I thought I might have stuffed something when I incorporated in my existing code but I just uploaded the original code and it is doing the same thing?
    Thanks
    Vix

  5. Just wanted you to know that I this tutorial helped me out big time and I liked it so much I turned around and bought your book. Thank you for breaking things down in a sane and non-convoluted manner!

  6. This was by a clear mile the clearest and most concise example of a pure css ham nav and it was beautiful – thank you!

  7. Hello and thank you very much. That’s so short and easy to understand and works as is.
    May I please ask, could you maybe do a similar tutorial or maybe please could you share your ideas shortly as an answer .. how to do it, simple like this, but with submenus? there is no need at all for fancy transitions or so, and, the submenu items should be visible until the user ‘clicks’ them away, just to stay like
    menuitem 1
    menuitem 1.1
    menuitem 1.1
    menuitem 2
    .. like this. Maybe kindly please share your ideas? Pure CSS if possible Thank you 🙂

  8. Thanks, nice presentation. I had some issues which I resolved. My issue was one that many people may have, that is converting an existing code base that already has an horizontal list li menu. It took quite a few changes to implement this. Such as not using any of the “Big Screen” code, and redoing the existing css to make it all play nice. All that said, thanks, saved me a ton of time, and a much simpler solution than any other way I saw available.

Leave a Comment

Your email address will not be published. Required fields are marked *