2 Steps Simple Responsive Pure CSS Hamburger Menu

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.



Download & Demo What Hamburger? How to Build
Useful Bits The End




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



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.



If you spot a bug, please feel free to comment below. I try to answer 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.



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



For you folks who have stumbled upon this guide, and have totally no idea on why or what people are calling a hamburger menu – You may have noticed the 3 bars symbol () on many websites and mobile applications. Yep, that is the hamburger with a patty sandwiched in between 2 buns.



Before some of you guys start to think that a “hamburger menu” is nothing but putting that 3 bars somewhere. Well, there is a little more to it. Typically, the hamburger will not show up on big screens. It is only on the smaller screens that the navigation menu will be collapsed, and the hamburger icon is used to show/hide the menu – That is what we will be building in this tutorial.




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



<nav id="hamnav">
  <!-- [THE HAMBURGER] -->
  <label for="hamburger">&#9776;</label>
  <input type="checkbox" id="hamburger"/>
  <!-- [MENU ITEMS] -->
  <div id="hamitems">
    <a href="index.html">Home</a>
    <a href="about.html">About</a>
    <a href="tech.html">Tech</a>
    <a href="games.html">Games</a>
    <a href="reviews.html">Reviews</a>

The HTML part should be pretty straightforward:

  • First, we need to create the wrapper for the entire navigation menu <nav id="hamnav">.
  • 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”.
  • Finally, we just sandwich the actual menu items <a> inside the  <div id="hamitems"> wrapper.
  • No Javascript is required here, as we will be using pure CSS to toggle show/hide the menu items.




/* Wrapper */
#hamnav {
  width: 100%;
  background: #000;
  /* Optional */
  position: sticky;
  top: 0;

/* Hide Hamburger */
#hamnav label, #hamburger { display: none; }

/* Horizontal Menu Items */
#hamitems { display: flex; }
#hamitems a {
  width: 20%; /* 100% / 5 tabs = 20% */
  padding: 10px;
  color: white;
  text-decoration: none;
  text-align: center;
#hamitems a:hover {
  background: #401408;

@media screen and (max-width: 768px){
  /* Show Hamburger Icon */
  #hamnav label { 
    display: inline-block; 
    color: white;
    background: #a02620;
    font-style: normal;
    font-size: 1.2em;
    padding: 10px;

  /* Break down menu items into vertical */
  #hamitems a {
    box-sizing: border-box;
    display: block;
    width: 100%;
    border-top: 1px solid #333;

  /* Toggle Show/Hide Menu */
  #hamitems { display: none; }
  #hamnav input:checked ~ #hamitems { display: block; }

html, body {
  padding: 0;
  margin: 0;
  font-family: arial, sans-serif;


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:

  • First, we will hide the hamburger menu icon by attaching display: none to #hamnav label and #hamburger – Since we do not need it on the big screen.
  • Next, we set #hamitems to display: flex.
  • Lastly, set the width of the menu items #hamitems a, and add some cosmetics.

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



The above “normal” CSS will display a horizontal menu on big screens. But on the smaller screens, we will need to break the menu down into a vertical one due to screen size constraints, and use the hamburger button to toggle show/hide the menu:

  • As usual, we will use the @media media query to apply a different style for small screens.
  • First, we set a display: inline-block to #hamnav label to show the hamburger icon.
  • Take note that the <input type="checkbox"/> remains hidden.
  • Then, we will break the menu items #hamitems a down to show in a vertical orientation by setting it to display: block and width: 100% instead.
  • Finally, we will hide the menu items #hamitems by default.
  • The magic happens with #hamnav input:checked ~ #hamitems and display: block. This will basically toggle show/hide the menu items as the user checks the hidden checkbox/hamburger button.




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



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.

#hamnav {
  position: sticky;
  top: 0;

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



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






Pure CSS Hamburger Menu (click to enlarge)



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!

25 thoughts on “2 Steps Simple Responsive Pure CSS Hamburger Menu”

  1. 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?

  2. 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!

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

  4. 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 🙂

  5. 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.

  6. Actually I was able to solve problem of menu appearing behind other elements by adding
    z-index: 99 !important;
    to my navigation. It works great now. Thanks for this guide!

  7. What is the purpose of using a check box input? This is the second article I’ve read on this subject, both of which call of the check box. And in both cases, using the provided code renders a visible check box on full size screens, and zero responsiveness to the navigation bar.

    1. Really!? How about “actually reading through the entire tutorial and watch the YouTube video”? 🙄 *Hint* The magic happens with #hamnav input:checked ~ #hamitems…

  8. This is amazing! I love it! I made a nice square button with
    nav label {
    /* … */
    border-radius: 5px;
    width: 48px;
    line-height: 48px;
    text-align: center;
    vertical-align: middle;

    One question, though: when the menu is opened, each link visually takes up the full width of the viewport, but most of it does not respond to click/tap. This can be seen in the browser with your example embedded on this page; you have to hover the mouse exactly over the text for the hyperlink to show. Is there any way to make the clickable zone for each navigation link take up the full width, including empty space? Thanks!

  9. After struggling with tons of tricks for hamburger menu (mobile view), i found this one is so simple, easy, and work for my web. No jquery or external script. Thanks.

  10. This was a lot easier to follow than other tutorials I’ve seen. However, mine isn’t working. The hamburger icon is present, but the menu doesn’t drop down once I click on it. Is there a way that we can fix this? I copy and pasted the code, so it should be working. I changed the background color, but that’s it. Also, is there a way that I can resize the hamburger icon. I tried everything with no luck. Thanks for your time and this tutorial.

    1. 1) Resizing the hamburger icon is as easy as adding label[for="hamburger"] { font-size: XX }
      2) The <input type="checkbox" id="hamburger"/> MUST be in the same container as the <ul> menu, since we are targeting them as siblings in CSS – #page-nav input:checked ~ ul { OPEN MENU }

  11. Johnny Baxter

    I echo the comment above, been looking at loads of tutorials on this today and this was by far the clearest I have found, really well set out and explained.

    I did find the ☰ code doesn’t display in some older browsers, and as the average age of the people using the website I am managing is probably quite old, I decided to create a little hamburger image instead and it works a treat, even on Chrome v18!


  12. That has to be the clearest Hamburger menu tutorial I have ever come across – none of the messing about with borders and box shadows to create the lines. Thank you

Leave a Comment

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