How to create a fully responsive navbar with Flexbox

Per - Jul 19 '19 - - Dev Community

In this article, I’ll explain how to create a navbar which adapts to various screen sizes using Flexbox along with media queries.

This tutorial can also be found as an interactive screencast in my free Flexbox course at Scrimba.

The setup

Let’s begin with the markup for a very simple navbar:

<nav>  
  <ul class="container">  
    <li>Home</li>  
    <li>Profile</li>  
    <li class="search">  
      <input type="text" class="search-input" placeholder="Search">  
    </li>  
    <li>Logout</li>  
  </ul>  
</nav>
Enter fullscreen mode Exit fullscreen mode

The <ul> element is our flex container and the <li> elements are our flex items. To turn it into a Flexbox layout we’ll do:

.container {  
  display: flex;  
}
Enter fullscreen mode Exit fullscreen mode

Which will result in the following layout:

I’ve added some styling, but that has nothing to do with Flexbox.
I’ve added some styling, but that has nothing to do with Flexbox.

As you can see, we have a bit of extra space on the right-hand side. This is because Flexbox lays out the items going from left to right, and each item is only as wide as its content forces it to be.

Since the flex container by default is a block level element (and is wider than the four items) we get the gap at the end.

The reason the search items is wider than the others is because input fields are by default set to size="20", which different browsers and operating systems interpret in different ways.

Responsiveness #1

To give our navbar basic responsiveness, we’ll simply give the search item a flex value of 1.

.search {  
  flex: 1;  
}
Enter fullscreen mode Exit fullscreen mode

This results in the search item expanding and shrinking with the width of the container, meaning we won’t get the extra space in the right-hand side.

While it makes sense to have the search item grow while the others stay fixed, you could argue that it can become too wide compared to the others. So if you prefer to have all the items grow with the width of the container instead, you can simply give all the items a flex value of 1.

.container > li {  
  flex: 1;  
}
Enter fullscreen mode Exit fullscreen mode

Here’s how that plays out:

You can also give the items different flex values, which would make them grow with different speeds. Feel free to experiment with that in this Scrimba playground.

For the rest of the tutorial, we’ll continue with the first solution, where the search items are the only one with a flex value.

Responsiveness #2

Our navbar works well on wide screens. However, on more narrow ones it gets into problems, as you can see here:

At some point, it’s not viable to have all items on the same row, as the container becomes too narrow. To solve this we’ll add a media query where we’ll split our four items into two rows. The media query will kick when the screen is 600px wide:

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

  .container {  
    flex-wrap: wrap;  
  }  

  .container > li {  
    flex-basis: 50%;  
  }

}
Enter fullscreen mode Exit fullscreen mode

First, we allow the Flexbox layout to wrap with flex-wrap. This is by default set to nowrap, so we’ll have to change it to wrap.

The next thing we do it set the items’ flex-basis value to 50%. This tells Flexbox to make each item take up 50% of the available width, which results in two items per row, like this:

Note: I’ve also centred the placeholder text in the search input field.
Note: I’ve also centred the placeholder text in the search input field.

Now we have two different states. However, this layout still doesn’t work on very small screens, like mobile screens in portrait mode.

If we continue shrinking the screen, it’ll end up like the image below.

What’s happened here is that the second row can’t fit two items anymore.

The logout and the search items are simply too wide, as you can’t shrink them down to below their minimum width, which is the width they need in order to fill the content inside of them.

The home and profile items are still able to appear on the same row though, so Flexbox will allow them to do so. This isn’t optimal, as we want all of our rows to behave in the same way.

Responsiveness #3

So as soon as one of the rows can’t fit two items in the width, we want none of the rows to have two items in the width. In other words, on very small screens we’ll actually make navbar vertical. We’ll stack the items on top of each other.

To achieve this we simply need to change our 50% width to 100%, so that each row only fits a single item. We’ll add this breakpoint at 400px.

@media all and (max-width: 400px) {  
  .container > li {  
    flex-basis: 100%;  
  }  
  .search {  
    order: 1;  
  }  
}
Enter fullscreen mode Exit fullscreen mode

In addition to this, I’d like to place the search item at the bottom, which is why I’m also targeting the search and give it an order value of 1.

This results in the following:

The reason order: 1; results in the search item being placed at the bottom are because flex items by default have a value of zero, and whatever item has a higher value than that will be placed after the others.

To see how it all plays out, here’s the gif from the top of the article:

Congrats! You now know how to create a fully responsive navbar using Flexbox and media queries.

If you’re interested in learning more about Flexbox, I’d recommend you to check out my free course at Scrimba.

Click the image to get to my free Flexbox course.Click the image to get to my free Flexbox course.

Thanks for reading! My name is Per, I’m the co-founder of Scrimba, and I love helping people learn new skills. Follow me on Twitter if you’d like to be notified about new articles and resources.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .