Responsive navigation and hamburger menu

If you’re trying to create a responsive navigation menu that works well on all screen sizes, this post will walk you in the right direction. Aside from the responsive header, you’ll also learn how to create a simple hamburger menu for smaller screen sizes.

End of this post, the source code is available for download.

Before we start building the header navigation & the hamburger menu, see the demo of the final product below.

How to create responsive header navigation & hamburger menu?

In this example, I will use HTML, CSS & a few lines of JavaScript. As you have seen on the live demo, the same header navigation works for all screen sizes. And this is what we are going to build.

I have the following project setup:

File & folders for hamburger menu project
Project setup

HTML markup

For the entire header navigation, I have the following HTML markup. This HTML contains a logo and the menu items (links).

<nav class="site-header">
	<div class="nav-logo">
	  <a href="index.html">
	    <img src="assets/images/logo.png" alt="logo">
	  </a>
	</div>
	<button class="hamburger">
		<img src="assets/images/menu.png" alt="menu toggle icon">
	</button>
	<div class="nav-links">
	  <ul>
	    <li><a href="index.html">Home</a></li>
	    <li><a href="#about">About Me</a></li>
	    <li><a href="#skill">Skills</a></li>
	    <li><a href="#service">Services</a></li>
	    <li><a href="#portfolio">Portfolio</a></li>
	    <li><a href="#testimonial">Testimonial</a></li>
	    <li><a href="#pricing">Pricing</a></li>
	    <li><a href="#contact">Contact</a></li>
	  </ul>
	</div>
</nav><!-- .site-header -->

As you see on the above HTML, the entire header is wrapped by a <nav> tag. It also helps search engines to better understand the navigation.

Then, I have a <div> that contains the logo.

After the logo, I have a button that contains a hamburger icon/image instead of text.

Finally, I have another <div> that contains the actual menus (list item).

In your HTML file (in my case, it’s index.html), if you copy & paste the above HTML, it will look something similar to the below screenshot.

HTML hamburger menu without CSS & JavaScript
HTML header navigation without CSS & JavaScript

As you see on the above code, the logo & the hamburger menu icon live in the “assets/images” directory.

So if your project setup is different than mine, make sure you updated the above two image paths in your HTML.

CSS (styles)

I wrote the following CSS to hide the hamburger icon on large devices and to make the header navigation nice.

.site-header {
  z-index: 10;
  font-family: 'Roboto Condensed', sans-serif;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
      -ms-flex-align: center;
          align-items: center;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
  background-color: #FFF;
}

@media screen and (min-width: 1250px) {
  .site-header {
    -webkit-box-pack: justify;
        -ms-flex-pack: justify;
            justify-content: space-between;
    -webkit-box-orient: horizontal;
    -webkit-box-direction: normal;
        -ms-flex-direction: row;
            flex-direction: row;
  }
}

.site-header .nav-logo {
  -ms-flex-item-align: start;
      align-self: flex-start;
  padding: 10px 5px 5px;
}

.site-header .nav-logo a img {
  max-width: 200px;
  height: auto;
}

@media screen and (min-width: 768px) {
  .site-header .nav-logo a img {
    max-width: 314px;
    height: auto;
  }
}

.site-header .nav-links {
  display: none;
  width: 100%;
  background-color: #DEF0FF;
}

@media screen and (min-width: 1250px) {
  .site-header .nav-links {
    display: block;
    background-color: #FFF;
  }
}

.site-header .nav-links ul {
  padding: 0;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
      -ms-flex-direction: column;
          flex-direction: column;
  -webkit-box-pack: end;
      -ms-flex-pack: end;
          justify-content: flex-end;
}

@media screen and (min-width: 1250px) {
  .site-header .nav-links ul {
    -webkit-box-orient: horizontal;
    -webkit-box-direction: normal;
        -ms-flex-direction: row;
            flex-direction: row;
  }
}

.site-header .nav-links ul li {
  list-style: none;
}

.site-header .nav-links ul li a {
  font-size: 18px;
  text-transform: uppercase;
  font-family: 400;
  color: #7f53ac;
  letter-spacing: 1.2px;
  padding: 10px 15px;
  text-decoration: none;
  display: block;
}

.site-header .nav-links ul li:hover {
  background-color: #efe0ff;
}

.site-header button {
  cursor: pointer;
  background: transparent;
  border: none;
  max-width: 50px;
  display: block;
  position: absolute;
  top: 10px;
  right: 10px;
}

@media screen and (min-width: 768px) {
  .site-header button {
    top: 20px;
  }
}

@media screen and (min-width: 1250px) {
  .site-header button {
    display: none;
  }
}

.nav-links.active {
  display: block;
}
/*# sourceMappingURL=style.css.map */

This CSS also contains the vendor prefixes so you don’t have to worry about browser compatibilities.

Anyways, based on my CSS, the breakpoint is below 1250px. It means that if the screen size is smaller than 1250px, the hamburger menu will appear. And it will disappear on 1250px and above.

With the above HTML & CSS in place, the header navigation menu will look like the following screenshot.

Header navigation menus in large and small devices
Header navigation menus in large and small devices

JavaScript code for the hamburger menu

Just like the above screenshot, you will see the hamburger menu icon on mobile devices but it won’t work until we write some JavaScript.

Don’t worry, we only need a few lines of JavaScript to complete the project.

To make the hamburger menu work (toggling), I wrote the following JavaScript:

const hamburger = document.getElementsByClassName("hamburger")[0]
const mobileNavs = document.getElementsByClassName("nav-links")[0]

hamburger.addEventListener("click", () => {
  mobileNavs.classList.toggle("active")
})

In my code, I have two variables (hamburger & mobileNavs). Since I don’t need to redeclare them so I went with constant (const). But you can have var or let, and in this context, it will not cause any issues.

In my HTML, I have two classes “hamburger & nav-links”

CSS classes in HTML

getElementsByClassName in JavaScript is the way to find all HTML elements by class name. My variables (const) contain the first element of each item using the “0” index “[0]”

In the next step, I have a method (addEventListener) that is listening for the “click” event. This method also contains an arrow function.

And this function toggles (adds and removes) a class name of “active” to the “mobileNavs” variable or the “nav-links” class.

The “.nav-links” or the navigation menu is hidden on small screens. I made it hidden using CSS “display: none.” But when you click the hamburger icon for the first time, it adds the “active” class to the “nav-links.” The “.active” has a CSS of “display: block.”

So if someone clicks the hamburger icon for the first time, the menu becomes visible. If you click the hamburger for the second time, the “active” class gets removed from the “nav-links.”

This is how the hamburger icon & navigation menu works together.

See also:

Download the source code

I tried to make you understand how things are working behind the scenes. And I explained the code along the way. But if you need to download the entire source code, use the following button.

After you download the source code from my GitHub repository, you will find all the necessary files and folders. However, the CSS file lives in the “sass” folder. But you don’t have to use SASS if you don’t like it. The only file you need in this folder is “style.css” and ignore all other partials (_file.scss). I included these files (partials) because some of you may like to use SASS. But if you don’t like SASS, just ignore the other files in the “sass” folder and only look/work on “style.css.”

See also:

Conclusion

I followed the mobile-first web design philosophy when writing code for the header navigation. There are various ways to make responsive navigation and hamburger menu. In this post, I showed you one of my preferred & simplest ways to do it.

Therefore if you still have any questions, let me know.