DEV Community

Cover image for Responsive Navigation Bar with mobile menu using HTML & CSS
Adam Nagy
Adam Nagy

Posted on

Responsive Navigation Bar with mobile menu using HTML & CSS

Any website on the web should be responsive in the modern web era. One of the must-do task is to create a navigation bar which is usable on both huge 4K monitors and small mobile devices. And this is exatly what we'll create in this tutorial.

Video tutorial

If you prefer to watch a a step-by-step, beginner friendly video instead, you can check out the video that I made on my YouTube channel:

Implementing the HTML

The HTMl markup will be really simple and will consist of two separate sections. We'll first create the markup that will be used for the desktop version, and after that we will implement the markup required for the mobile menu.

HTML markup for the desktop version

We wrap everything inside of header tags, and it will make our site more accessible as it helps screen readers. Inside the header we'll place a logo. For the sake of this example this will be a simple text wrapped inside an a tag, which navigates to the homepage. Below the brand div, we will have a nav wrapper. It also helps screen readers to understand the page. Inside our nav we'll have an unordered list, which will hold all of our navigation links. Every navigation link will have the same basic structure. Each of them will be a list item (li), and inside that we will have an a tag which links to separate pages. I'll also give an id to the login and signup navigation for further styling.

<header>
   <div id="brand"><a href="/">MyCompany</a></div>
   <nav>
     <ul>
       <li><a href="/home">Home</a></li>
       <li><a href="/products">Products</a></li>
       <li><a href="/about">About</a></li>
       <li id="login"><a href="/login" >Login</a></li>
       <li id="signup"><a href="/signup">Signup</a></li>
     </ul>
   </nav>
</header>
Enter fullscreen mode Exit fullscreen mode

HTML markup for the mobile version

At small screen sizes, we will use a hamburger menu to toggle the navigation menu. For the hamburger icon you can use any external icon libraries, like FontAwesome, but in this tutorial, I'll create my own hamburger icon using HTML and CSS.

The hamburger icon 🍔

The html structure of the icon will be really simple. First we'll add a container div with the id of hamburger-icon. We will use this wrapper div to style and positions the bars inside the hamburger icon. We'll also add an onclick event handler, which will toggle our mobile menu. We'll implement this later in javascript. Inside our container we'll add three divs. They have separate classnames, and we'll use those for makeing our micro animation which will fade away the middle bar and form an X from the bottom and top one.

<div id="hamburger-icon" onclick="toggleMobileMenu(this)">
  <div class="bar1"></div>
  <div class="bar2"></div>
  <div class="bar3"></div>
</div>
Enter fullscreen mode Exit fullscreen mode

In CSS, we'll center the icon vertically using margin: auto 0, and hide it by default using display: none. We'll make it visible through a media query if the screen is less than 600px wide. (You can also do it in a mobile first approach and show it by default and hide it if the screen is wider than 600px). We'Ll give the divs inside the wrapper a fixed width and height and give them a little vertical spacing with margin. When the mobile menu is open (open class is added to the mobile menu), we'll rotate the first bar by -45 degrees and adjust it with translate. We'll hide the second bar by setting the opacity to zero, and we'll also do the same transformations to the last element as we did for the first, but in the opposite direction.

#hamburger-icon {
  margin: auto 0;
  display: none;
  cursor: pointer;
}

#hamburger-icon div {
  width: 35px;
  height: 3px;
  background-color: white;
  margin: 6px 0;
  transition: 0.4s;
}

.open .bar1 {
  -webkit-transform: rotate(-45deg) translate(-6px, 6px);
  transform: rotate(-45deg) translate(-6px, 6px);
}

.open .bar2 {
  opacity: 0;
}

.open .bar3 {
  -webkit-transform: rotate(45deg) translate(-6px, -8px);
  transform: rotate(45deg) translate(-6px, -8px);
}
Enter fullscreen mode Exit fullscreen mode

Mobile HTML markup

Below the bars that we created for the hamburger icon in the previous section, we'll add the same navigation menu that we had in the desktop HTML markup section. The only important difference is that the unordered list has a class mobile-menu. We will use this class to apply all the mobile related styles.

<div id="hamburger-icon" onclick="toggleMobileMenu(this)">
  <div class="bar1"></div>
  <div class="bar2"></div>
  <div class="bar3"></div>
  <ul class="mobile-menu">
    <li><a href="/home">Home</a></li>
    <li><a href="/products">Products</a></li>
    <li><a href="/about">About</a></li>
    <li id="login"><a href="/login" >Login</a></li>
    <li id="signup"><a href="/signup">Signup</a></li>
  </ul>
</div>
Enter fullscreen mode Exit fullscreen mode

Finishing up the HTML.

There is two things we have to add:

  • A link to the css stylesheet in the head section that we'll create:
<link rel="stylesheet" href="styles.css" />
Enter fullscreen mode Exit fullscreen mode
  • Importing our javascript file at the end of the body:
<script src="index.js"></script>
Enter fullscreen mode Exit fullscreen mode

Implement the CSS part

First I'll import a Google font called Poppins, then reset every browser default margins and paddings and also set the box-siting to border-box. Then for the body we'll set out brand new font and set a dark background and white text color.

@import url("https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap");

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}

body {
  background-color: #353836;
  color: white;
  font-family: "Poppins", sans-serif;
}
Enter fullscreen mode Exit fullscreen mode

Next we'll focus on the header wrapper and the logo. We'll remove all text decoration (underline) from any links inside the header. For the header we'll set a little bit of left and right padding, give it a dark background color, and a fixed height. We'll also set the display to flex, and to have the logo on the right and the navigation links on the left we'll add justify-content: space-between;. For the brand, we'll set the desired font size and weight, and also center it vertically using flexbox.

header a {
  text-decoration: none;
}

header {
  padding: 0 20px;
  background-color: #1d1f1d;
  height: 50px;
  display: flex;
  justify-content: space-between;
}

#brand {
  font-weight: bold;
  font-size: 18px;
  display: flex;
  align-items: center;
}

#brand a {
  color: #09c372;
}
Enter fullscreen mode Exit fullscreen mode

Regarding the navigation links we'll remove any bullet points from the list, make the container full width and center it vertically using flexbox. We'll set a white color for the links and add some spacing using paddings and margins to the list items. I'll also add a hover effect to scale the links up a bit when they are hovered.

ul {
  list-style: none;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: space-around;
}

ul a {
  color: white;
}

ul li {
  padding: 5px;
  margin-left: 10px;
}

ul li:hover {
  transform: scale(1.1);
  transition: 0.3s;
}
Enter fullscreen mode Exit fullscreen mode

The login and signup links will have a different button-like styling. We'll give them more spacing and round borders and use blue and red colors to differentiate them from the other links.

#login,
#signup {
  border-radius: 5px;
  padding: 5px 8px;
}

#login {
  border: 1px solid #498afb;
}

#signup {
  border: 1px solid #ff3860;
}

#signup a {
  color: #ff3860;
}

#login a {
  color: #498afb;
}
Enter fullscreen mode Exit fullscreen mode

Now it's time to implement the styles for the mobile menu. By default the menu will be hidden so we'll apply display: none;. We'll position the mobile menu absolutely, and place it right below the header, to do that we have to set a top offset of 50px, as it is the fixed height of the header. We want the mobile menu to take the full remaning space of the site (besides the header), so will make it full width, and we'll set the high to be 100% and substract the height of the header from it.

When the mobile menu is open, we want to display it, and we'll use flexbox to overrode the display:none. We'll use flex-direction column to stack the links below each other, center them horizontally and make them start from the beginning of the flex container. We'll also add a little bottom margin to the links to amke them a little space to breath.

.mobile-menu {
  display: none;
  position: absolute;
  top: 50px;
  left: 0;
  height: calc(100vh - 50px);
  width: 100%;
}

.open .mobile-menu {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
}

.mobile-menu li {
  margin-bottom: 10px;
}
Enter fullscreen mode Exit fullscreen mode

Lastly we have to add the media query to hide the desktop menu, when we are on mobile size and display the hamburger icon when we are on mobile screen size. I'll use 600px as the breakpoint for mobile.

@media only screen and (max-width: 600px) {
  header nav {
    display: none;
  }

  #hamburger-icon {
    display: block;
  }
}
Enter fullscreen mode Exit fullscreen mode

A little bit of javascript

We will have one lonely javascript function in our index.js file that will toggle the mobile menu between open and closed states. We already added this event handler in the HTML section. We will use the reference that we passed from the HTML and modify its classList using it. The toggle function will check wether the provided class is present on the element and if it is then it will remove it and if it's not then it will add it.

function toggleMobileMenu(menu) {
    menu.classList.toggle('open');
}
Enter fullscreen mode Exit fullscreen mode

Links for the full source code

You can check the full source code here:

Where you can learn more from me?

I create education content covering web-development on several platforms, feel free to 👀 check them out.

I also create a newsletter where I share the week's or 2 week's educational content that I created. No bull💩 just educational content.

🔗 Links:

Top comments (5)

Collapse
 
ddking8899 profile image
ddking-products

Can I use this nav bar in my project. Please ...............................

Collapse
 
javascriptacademy profile image
Adam Nagy

For sure :)

Collapse
 
ddking8899 profile image
ddking-products

Thank You Sir

Collapse
 
meektortoise profile image
MeekTortoise • Edited

how can i make it so it can be seen on every page without copying the code to every page?

Collapse
 
iswatinagwanshi profile image
Swati Nagwanshi

You can create common header. For creating this you can take refrence from youtube.