Creating a Navigation Bar with Flexbox
Tags: webdev, css, tutorial
Published: 2020-02-14 01:09:43

---
title: "Creating a Navigation Bar with Flexbox"
description: "Use Flexbox to build a navigation bar with elements evenly-spaced on large screens, and vertically stacked on small screens, all with minimal HTML and CSS."
published: true
canonical_url: https://bphogan.com/2020/2020/02/13/css-menu
tags: webdev,css,tutorial
---

Creating a navigation bar for a site used to be challenging, especially when you want a horizontal navigation bar on large screens. You'd need to do the math to split up your elements, account for padding and margin width, and then hope nobody wanted changes later.

With [Flexbox](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox) widely available in browsers, creating your navigation bar involves much less code. 

In this tutorial you'll build a navigation bar with elements evenly-spaced on large screens, and vertically stacked on small screens, and you'll build it all with minimal HTML and CSS.

## Creating the HTML

Create a new HTML file called `nav.html` and place the following HTML skeleton in the file:

```html
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My Navbar Example</title>
  </head>
  <body>

  </body>
</html>

```

This template defines the document's language, the character encoding, the viewport size, so mobile devices will zoom and scale the page appropriately, and the page's title.

In the `<body>` of the page, add a `<nav>` element that contains a few links:

```html
<nav>
  <a href="#">Home</a>
  <a href="#">About</a>
  <a href="#">Products</a>
  <a href="#">Support</a>
</nav>
```

This navigation element only contains `<a>` tags. It does not contain an unordered list or other markup like you might have seen in other menu examples. This is all the markup you need to define your menu, as Flexbox can handle all of the alignment and styling. If you need to develop a more complex menu, with sections, submenus, and other elements, you might benefit from additional structural elements, but that's not the case here. 

Now let's add the styles.

## Styling the Menu

Styling the menu involves two steps:

* Defining the placement of elements
* Defining the appearance of elements

Start by defining the placement. The goal for this menu is that it displays vertically on small screens and horizontally on large screens. You'll end up writing less code if you build your CSS "mobile first"; in other words, style everything for the small screen first, and then add media queries for the larger screens. 

In your `nav.html` file, add a `<style>` element to the `<head>` section. 

```html
<head>
...
  <style>
  
  </style>
</head>
```

In a larger project, you'd use an external stylesheet with a `<link>` element, but for this example, keep everything in one file so you can reference it later when you're working on your own projects.

Within the `<style>` section of the page, add a new definition for the `nav` element that defines it as a [flex container](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox#The_flex_container), ensures its child elements are spaced apart evenly, and that the elements are stacked vertically:

```css
nav {
  display: flex;
  justify-content: space-between;
  flex-direction: column;
}
```

The `justify-content` option ensures there's even spacing between child elements, while `flex-direction` determines whether child elements are displayed vertically stacked (`column`), or horizontally placed (`row`). Stacking elements vertically by default follows the "mobile first" philosophy.

Next, add a media query that targets larger displays and defines `flex-direction` again, but this time using the `row` value:

```css
@media only screen and (min-width: 768px) {
  nav { flex-direction: row; }
}
```

This media query looks for screens with a minimum width of 768 pixels. In your own projects, use your browser's developer tools to simulate mobile devices and adjust the width and identify a width that works for you. 

The flex container is defined, so the next step is to style the individual elements. The flex container settings you specified in the `nav` element's style definition apply to direct child elements only. That's one reason this code doesn't use additional markup like bulleted lists. If you did that, you'd have to make the list the flex container instead.

Add the following style definition to evenly space your elements:

```css
nav a{
  flex: 1;
  text-align: center;
  margin: 0.25em;
  padding: 0.25em;
}
```

The [flex](https://developer.mozilla.org/en-US/docs/Web/CSS/flex) property defines how the element will shrink or grow. Using `flex: 1` on all of the `<a>` elements makes them all take up the same size.  If you wanted one of the elements to be twice as wide as the others, you'd specify one of those to use `flex: 2`.

`text-align: center` centers the text inside of each element. The `margin` and `padding` ensure there's even spacing inside and outside of each element.

This defines the placement of the elements. Now define the appearance. Add a border around each navigation item, change the color, and remove the underline:

```css
nav a{
  flex: 1;
  text-align: center;
  margin: 0.25em;
  padding: 0.25em;
  border: 1px solid #ddd;
  text-decoration: none;
  color: #555;
}
```

Your menu is complete. Your entire file should look like this:

```html
<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My Navbar Example</title>
    <style>
      nav {
        display: flex;
        justify-content: space-between;
        flex-direction: column;
      }

      @media only screen and (min-width: 768px) {
        nav { flex-direction: row; }
      }

      nav a{
        flex: 1;
        text-align: center;
        margin: 0.25em;
        padding: 0.25em;
        border: 1px solid #ddd;
        text-decoration: none;
        color: #555;
      }

    </style>
  </head>
  <body>
    <nav>
      <a href="#">Home</a>
      <a href="#">About</a>
      <a href="#">Products</a>
      <a href="#">Support</a>
    </nav>
  </body>
</html>
```

Verify that it does, and save the file. Open the file in your browser and you'll see your horizontal navbar:


<figure class="post-figure">
  <img src="https://bphogan.com/2020/02/13/css-menu/images/horizontal_hu16901f6a8a0709e1256c5acc75933cc9_13466_700x0_resize_box_2.b295f667652817e88f08e2c03d512131f65a4204a53a629ea29a2479caf952fd.png"
         width="700" height="30"
         alt="The horizontal navbar" />
    

  <figcaption>The horizontal navbar</figcaption>
</figure>

Shrink the browser window below 768 pixels and you'll see the vertical menu:


<figure class="post-figure">
  <img src="https://bphogan.com/2020/02/13/css-menu/images/vertical_huae646a029830c60556b80986300e7249_21941_700x0_resize_box_2.a51105444baeadbb0ac16f8b65307a8e63b8154bda60c1355c08babae03057b9.png"
         width="700" height="159"
         alt="The horizontal navbar" />
   
  <figcaption>The horizontal navbar</figcaption>
</figure>

## Conclusion

In this tutorial you explored the Flexbox feature of CSS. Flexbox lets you build a navigation element with much less code than you could in the past, but you can also use it for things like image galleries, user interface panes, or other elements you need to align horizontally or vertically. You could even use it for entire layouts. Explore Flexbox and see how you can fit it in to your next project.

Like this post? Support my writing by [purchasing one of my books about software development](https://bphogan.com/books).