Skip to content

How to Create a Responsive Navbar (Just Using Flexbox)

The navigation bar (aka nav bar) is one of the most significant parts of a website.

And making it responsive is even more crucial.

In this article, we’ll learn how to create a perfectly responsive navbar using simple HTML, CSS, and a little JavaScript.

But before moving ahead, here’s the table of content if you want to jump around:

  1. Writing the HTML
  2. Writing the CSS
  3. Making the Navbar Responsive
  4. Extra Improvements

How to Create a Responsive Navbar

Now don’t worry. I’ll not bore you with unnecessary details like “What is a responsive navbar” or “Why is it important”. I guess you already know all of that stuff.

Although I want to clarify one thing, I’m assuming you already have a basic understanding of the following CSS concepts:

  1. Basic properties
  2. CSS box model
  3. Flexbox
  4. Basic Media Query
  5. Click event in JavaScript

Okay, let’s first write the HTML.

HTML for a Responsive Navbar

Firstly, this is the example responsive navbar with a logo we want to create:

Responsive navbar preview example

As you can see, here we have three parts: a logo, navigation links, and a search bar.

So in the HTML, we’ll create a main wrapper, and it’ll have three elements inside it.

An image for the logo, a nav for the 3 navigation links, and a search bar for the search input box and the search button.

Like this

<header>
<img src="logo.png" alt="Logo" class="logo">
<div class="mobileMenuWrapper">
<nav class="navigation">
<a href="#">gallary</a>
<a href="#">events</a>
<a href="#">pricing</a>
</nav>
<div class="searchBar">
<input type="text" name="search" placeholder="Search" class="searchInputBox">
<button class="searchButton">
<i class="fa-solid fa-magnifying-glass"></i>
</button>
</div>
<i class="hamburgerMenu fa-solid fa-bars"></i>
</div>
</header>
HTML for the navbar

Here, as you can see, I wrapped the navigation and search bar in an additional wrapper with the class mobileMenuWrapper.

It has no use on wider screens. But when the screen gets smaller, we’ll use it as the main menu container or background. It will cover the screen when the menu is opened.

And after the search bar, we also added another element (the <i> tag). It’s nothing but the hamburger menu icon that we’ll use from the Font Awesome website.

Similarly, we have another icon at the end (with the class hamburgerMenu). It’ll act as the hamburger menu icon on mobile screens.

This was all about the markup for creating a responsive navbar. Now let’s move on to the interesting stuff: CSS.

Adding the CSS

So the first thing we’ll do is make the header a flex container with the flex-direction set to “row” (which is the default value).

In Flexbox and Grid, only the direct children are considered flex items. In this case, there are two flex items: The logo image and the mobile menu wrapper.

To align these two elements at either end of the header with space in between, we’ll set the justify-content property to “space-between”.

However, note that we’re aligning the mobileMenWraper. This will move both navigation and search bar to the end. But we only want the search bar at the end, not the navigation.

So to achieve this, we’ll make the navigation’s position absolute and center it horizontally.

Additionally, to lay the links inside the navigation horizontally, we make the navigation container a flex container with the flex-direction set to “row”.

Here’s how:

.navigation {
/* To center it within the body horizontally */
position: absolute;
left: 50%;
transform: translateX(-50%);

display: flex;
column-gap: 30px; /* Gap between the links in desktop version */
row-gap: 10px; /* Gap between the links in hamburger menu */
}
CSS for navigation

And initially set the display for the hamburger to none (as we want it visible only on mobile screens).

So this was the main logic for creating a navbar for wider screens. But now we have to make it responsive for smaller screens as well.

Although, we also need to give some basic styling to all the elements. So I covered them in the next section, but if you want to skip it, you can directly go to the mobile menu part.

Basics CSS for the Navbar Elements

Firstly, we want to set a fixed size for the logo because it’s too big.

And here we’ll also set the mix-blend-mode to “multiply” because our logo image also has a background. This will make it blend with the body background.

Like this:

.logo {
height: min(45px, 13vw); /* It'll be 50px high on wider screens and 13vw on smaller ones */
mix-blend-mode: multiply;
}
CSS for the Logo

Here, the min function returns the minimum value out of two values.

On wider screens, 13vw will be bigger than 45px hence the height of the logo on wider screens will be 45px but on the smaller screens where 13vw is smaller than 45px, the height of the logo will be 13vw.

This will ensure that the height of the logo will not be too large on smaller screens.

And the width of the logo will be by default “auto”.

We’ll also give some other basic styling to the navigation links and hamburger menu icon, like this:

.navigation a {
text-decoration: none;
color: var(--darkContrast);
font-family: "EB Garamond", serif;
font-size: 1.1rem;
font-weight: bold;
letter-spacing: 1px;
}

.hamburgerMenu {
cursor: pointer;
display: none;
position: absolute;
right: 15px;
top: 15px;
font-size: 1.6rem;
}
CSS for navigation links and hamburger menu icon

Coming to the styling for the search bar…

Firstly, remove the default styling for the searchInputBox and searchButton. Then make the searchBar a flex container so that the button and search input are laid horizontally instead of vertically.

Like so:

.searchInputBox,
.searchButton {
border: none;
outline: none;
background-color: transparent;
}

.searchBar {
display: flex;
border-radius: 100px;
}
CSS for search bar

Okay, now the navbar is perfect for wider screens, let’s make it responsive.

Making the Navbar Responsive

So currently the navigation bar looks like this:

The responsiveness problem

As you can see when we narrow down the viewport, the search bar starts to overlap with navigation.

That’s why on the smaller screens, we only want the logo and the hamburger menu to be visible. And when the user clicks on the hamburger menu icon, we’ll open the hamburger menu and show the navigation links and search bar inside it.

For doing that…

Firstly, we’ll set the display of navigation and search bar to “none” using media query and then make the hamburger menu icon visible.

Using this:

@media only screen and (max-width: 600px) {

/* If the viewport width is small, hide the navigation and searchbar */
.navigation{
display: none;
}

.searchBar {
display: none;
}

/* And just show the hamburger menu */
.hamburgerMenu {
display: block;
}
}
Media query for the responsiveness

Now, on the smaller screens, we’ll have a logo on the left side and the hamburger menu on the other.

The next thing is to open the hamburger menu when the user clicks on the icon.

So for that, we’ll use JavaScript to detect the click and then toggle a class “clicked” on click:

const hamburgerMenu = document.getElementsByClassName("hamburgerMenu")[0]
const mobileMenuWrapper = document.getElementsByClassName("mobileMenuWrapper")[0]

hamburgerMenu.addEventListener("click", showMobileMenu)

function showMobileMenu() {
mobileMenuWrapper.classList.toggle("clicked");
}
JavaScript for click event

What will this do?

Well, normally the mobileMenuWrapper has no class named “clicked” so when the icon is clicked, it’ll toggle that class. When the menu is opened, the class will be removed.

Now let’s use this clicked class to design the menu for the mobile screen.

Firstly, target the mobileMenuWrapper when it has the “clicked” class and then style it.

This will basically apply the CSS to mobileMenuWrapper only when the icon is clicked.

So make it a flex container with flex-direction set to “row” as we now want to display the navigation links and the search bar vertically.

Then set its position to “absolute” with its top, right, bottom, and left all to zero so that it covers the whole screen when the menu is opened.

Also, give it some basic styling like this:

  .mobileMenuWrapper.clicked {
display: flex;
position: fixed;

/* This will stretch the menu on the whole screen */
top: 0;
right: 0;
bottom: 0;
left: 0;

padding-top: 10px;
background-color: var(--complimentaryColor);
flex-direction: column;
gap: 10px;
}
CSS for hamburger menu

But we have a problem.

When the icon is clicked, the hamburger menu will open and cover the whole screen. But still we can can scroll the body.

Hence, to avoid that, we’ll also toggle a class for the body using this:

document.body.classList.toggle("blockScroll");
Another line inside the showMobileMenu function

Then target that class and set its overflow to “hidden” like this:

.blockScroll{
overflow: hidden;
}
Blocking the scroll

This problem is solved.

On the hamburger menu, we want the navigation links to be laid vertically, so let’s target the navigation when the menu is clicked and make it a flex container with flex-direction set to “column”. Also, we’ll need to set position to “relative” because in mobile version, it was set to “absolute”.

.mobileMenuWrapper.clicked .navigation {
/* Lay it vertically, instead of horizontally */
display: flex;
position: relative;
flex-direction: column;
align-items: center;

}

Now the only thing remaining is searchbar.

Previously, we’ve set its display to “none” inside the media query. Therefore, to make it visible, we’ll set it to “flex” and some other basic styling like this:

.mobileMenuWrapper.clicked .searchBar {
display: flex;
width: 80%;
align-self: center;
}

.mobileMenuWrapper.clicked .searchInputBox {
width: 90%;
}

Until this point, the navbar looks like this:

Minor problems with the navbar.

Extra Improvements

Although it looks almost perfect, it needs three minor improvements:

  1. We need to turn the hamburger icon to a cross mark when the menu is opened.
  2. Initially, only display the search icon. Show the full search bar with animation only when the user hovers over it.
  3. We can also add a 1s transition to the hamburger menu.

For changing the icon, we just need to toggle these two classes:

hamburgerMenu.classList.toggle("fa-xmark");
hamburgerMenu.classList.toggle("fa-bars");
Classes for cross mark and hamburger menu icon

Here, the fa-xmark class is a Font Awesome class for the cross mark and the fa-bars class is for hamburger menu icon.

When the menu opens, it will remove the "fa-xbars" class and add "fa-xmark". When it closes, it will remove "fa-xmark" and add "fa-bars".

For the searchbar, initially remove the border and set the input box width to 0. Show them only when the searchbar is hovered.

.searchBar:hover {
border: 2px solid var(--blackReplacementColor);
}

.searchBar:hover .searchInputBox {
width: min(150px, 17vw);
}

Lastly, add the transition to menu like this:

.mobileMenuWrapper {
transition: 1s;
}

That’s it. That’s how simple it is to create a perfectly responsive navigation bar just using HTML, CSS and a little JavaScript.

And you might have already realized the important role that flexbox played here. So, if you want to grab my free ebook “21 Clever Tricks Using Flex & Grid”, you can download it here.