Advertisement
CSS

Easy HTML 5 & CSS 3 Navigation Menu

Post image

Note: I have created an updated version of this tutorial here. Enjoy.

With HTML 5 and CSS 3 now standard in most modern browsers, web developers can create interactive, attractive menus with ease. A few years ago we would be looking at using Javascript for many of the modern features, not now!

Here's what we'll be creating in this tutorial:

See the Pen LKsez by lawnch (@lawnch) on CodePen

HTML

HTML 5 has many new elements/tags, the one we're most interested in is <nav>. The <nav> element works in a similar way to <div> but it'll make it easier for screen readers and web bots to interoperate your page.

Using Lists

An important part of creating a site navigation is understanding that the navigation is a list of links around your site.

What does that mean?

You need to use an unordered list to store your links, not a table!

HTML: the code

The HTML code is therefore very simple. We use <nav> like a div and we use an unordered list (<ul>). Let's get started!

<nav>
	<ul>
		<li><a href="home.html">Home</a></li>
		<li><a href="about.html">About</a></li>
		<li><a href="help.html">Help</a></li>
	</ul>
</nav>
	

This is a very simple navigation with a single tiered list. To create a dropdown menu we need to add a nested list inside one of the list-item elements.

<nav>
	<ul>
		<li><a href="home.html">Home</a></li>
		<li>
			<a href="products.html">Products <span class="caret"></span></a>
			<div>
				<ul>
					<li><a href="products.html#chair">Chair</a></li>
					<li><a href="products.html#table">Table</a></li>
					<li><a href="cooker.html">Cooker</a></li>
				</ul>
			</div>
		</li>
		<li><a href="about.html">About</a></li>
		<li><a href="help.html">Help</a></li>
	</ul>
</nav>
	

Inside the products 1st tier item we have 2 elements.

  1. Products link - You don't need to use the "href" attribute but I always add a fallback.
  2. Div - This contains our drop down menu or 2nd tier menu

If you wanted to create more levels to your menu then it's very easy, keep embedding menus inside your list items. My recommendation is to use 3/4 levels at most as users will get lost very easily.

CSS

For my example I'll be using the following body styling:

body {
	background-color: #EBE8E4;
	color: #222;
	font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
	font-weight: 300;
	font-size: 15px;
}
	

First of all we need to style our nav element. You do this exactly the same way as styling a div in CSS.

nav {
	background-color: #fff;
	border: 1px solid #dedede;
	border-radius: 4px;
	box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.055);
	color: #888;
	display: block;
	margin: 8px 22px 8px 22px;
	overflow: hidden;
	width: 90%; 
}
	

Let's go through some of the CSS 3 and important styles in there -

  1. Border-radius: This gives us the rounded corners that used to be so hard to create. We've set a 4px radius across all corners.
  2. Box-shadow: Add a nice shadow around our element. Syntax - box-shadow: h-shadow v-shadow blur spread color inset;
  3. RGBA: RGB simply means Red, Green, Blue, it's an alternative to using HEX colours. By having RGBA we've specified an "Alpha" or opacity value to our shadow
  4. Margin: Done using the web developers compass (top, right, bottom, left), it specifies the "gap" around the element
  5. Overflow: This will stop any items breaking out of our element - used to fix a hover state on the list items

The next part of our HTML is the list, let's create the CSS for that.

nav ul {
	margin: 0;
	padding: 0;
}

	nav ul li {
		display: inline-block;
		list-style-type: none;
		
		-webkit-transition: all 0.2s;
		-moz-transition: all 0.2s;
		-ms-transition: all 0.2s;
		-o-transition: all 0.2s;
		transition: all 0.2s; 
	}
	
		nav > ul > li > a {
			color: #aaa;
			display: block;
			line-height: 56px;
			padding: 0 24px;
			text-decoration: none;
		}
	

There are 2 important parts of the above code:

  1. Inline-block: By setting our list-items to inline block we can arrange them in a horizontal line without using float
  2. CSS Transitions: We've used a very basic transition here, "all" means all CSS attributes and "0.2s" refers to the amount of time they'll take to transition

Creating a CSS triangle

CSS allows us to create different shapes by changing the size of different borders. This means that we can create a drop-down icon / down arrow by purely using CSS.

 
nav > ul > li > a > .caret {
	border-top: 4px solid #aaa;
	border-right: 4px solid transparent;
	border-left: 4px solid transparent;
	content: "";
	display: inline-block;
	height: 0;
	width: 0;
	vertical-align: middle;
	
	-webkit-transition: color 0.1s linear;
	-moz-transition: color 0.1s linear;
	-o-transition: color 0.1s linear;
	  transition: color 0.1s linear; 
}
	

As you can see, we've set the border-top to 4px and are using the left and right borders to shape the top border into the shape we want.

Creating CSS triangles is simple and easy to do. Have a play around and see what you can come up with. Here are some simple combinations:

  • Up Arrow: Border-bottom: 5px solid, border-left: 5px transparent, border-right: 5px transparent
  • Down Arrow: Border-top: 5px solid, border-left: 5px transparent, border-right: 5px transparent
  • Left Arrow: Border-left: 5px solid, border-top: 5px transparent, border-bottom: 5px transparent
  • Right Arrow: Border-right: 5px solid, border-top: 5px transparent, border-bottom: 5px transparent

Hover States

An important rule when creating user interface designs is to make sure things change when they expect them to, i.e. Hover states on links are very important. Below are our basic hover states for the list items in our 1st tier navigation.

 
        nav > ul > li:hover {
          background-color: rgb( 40, 44, 47 );
        }

        nav > ul > li:hover > a {
          color: rgb( 255, 255, 255 );
        }

        nav > ul > li:hover > a > .caret {
          border-top-color: rgb( 255, 255, 255 );
        }
	

CSS 3 Drop-down Menu

Finally we need to style the containing div that holds our 2nd menu. There are 2 important parts to this styling:

  1. Position Absolute: This will place the menu outside of the nav bar and will allow you to display it on-top of other content
  2. Display None: You need to display none by default so the menu is hidden until someone hovers over the parent link
nav > ul > li > div {
	background-color: rgb( 40, 44, 47 );
	border-top: 0;
	border-radius: 0 0 4px 4px;
	box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.055);
	display: none;
	margin: 0;
	opacity: 0;
	position: absolute;
	width: 165px;
	visibility: hidden;
	z-index: 100;
	
	-webkit-transiton: opacity 0.2s;
	-moz-transition: opacity 0.2s;
	-ms-transition: opacity 0.2s;
	-o-transition: opacity 0.2s;
	-transition: opacity 0.2s;
}

	nav > ul > li > div ul > li {
		display: block;
	}
	
		nav > ul > li > div ul > li > a {
			color: #fff;
			display: block;
			padding: 12px 24px;
			text-decoration: none;
		}
	
	nav > ul > li > div ul > li:hover > a {
		background-color: rgba( 255, 255, 255, 0.1);
	}
  	

The question I get asked most about this code is - How do I make the drop-down menu appear? This is how -

nav > ul > li:hover > div {
	display: block;
	opacity: 1;
	visibility: visible;
}
	

The above code is saying when you hover over the parent list item then give the div element inside it the following style.

The Code - Two Tier Dropdown

Note: I've created an update to this tutorial below with a third tier, if you wish to use 3 levels then please see the update below for the full code.

HTML

Download here:

<nav>
	<ul>
		<li><a href="home.html">Home</a></li>
		<li>
			<a href="products.html">Products <span class="caret"></span></a>
			<div>
				<ul>
					<li><a href="products.html#chair">Chair</a></li>
					<li><a href="products.html#table">Table</a></li>
					<li><a href="cooker.html">Cooker</a></li>
				</ul>
			</div>
		</li>
		<li><a href="about.html">About</a></li>
		<li><a href="help.html">Help</a></li>
	</ul>
</nav>
	

CSS

Download here:

body {
  background-color: #EBE8E4;
  color: #222;
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
  font-weight: 300;
  font-size: 15px;
}

nav {
  background-color: #fff;
  border: 1px solid #dedede;
  border-radius: 4px;
  box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.055);
  color: #888;
  display: block;
  margin: 8px 22px 8px 22px;
  overflow: hidden;
  width: 90%; 
}

  nav ul {
    margin: 0;
    padding: 0;
  }

    nav ul li {
      display: inline-block;
      list-style-type: none;
      
      -webkit-transition: all 0.2s;
        -moz-transition: all 0.2s;
        -ms-transition: all 0.2s;
        -o-transition: all 0.2s;
        transition: all 0.2s; 
    }
      
      nav > ul > li > a > .caret {
        border-top: 4px solid #aaa;
        border-right: 4px solid transparent;
        border-left: 4px solid transparent;
        content: "";
        display: inline-block;
        height: 0;
        width: 0;
        vertical-align: middle;
  
        -webkit-transition: color 0.1s linear;
     	  -moz-transition: color 0.1s linear;
       	-o-transition: color 0.1s linear;
          transition: color 0.1s linear; 
      }

      nav > ul > li > a {
        color: #aaa;
        display: block;
        line-height: 56px;
        padding: 0 24px;
        text-decoration: none;
      }

        nav > ul > li:hover {
          background-color: rgb( 40, 44, 47 );
        }

        nav > ul > li:hover > a {
          color: rgb( 255, 255, 255 );
        }

        nav > ul > li:hover > a > .caret {
          border-top-color: rgb( 255, 255, 255 );
        }
      
      nav > ul > li > div {
        background-color: rgb( 40, 44, 47 );
        border-top: 0;
        border-radius: 0 0 4px 4px;
        box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.055);
        display: none;
        margin: 0;
        opacity: 0;
        position: absolute;
        width: 165px;
	visibility: hidden;
	z-index: 100;
  
        -webkit-transiton: opacity 0.2s;
        -moz-transition: opacity 0.2s;
        -ms-transition: opacity 0.2s;
        -o-transition: opacity 0.2s;
        -transition: opacity 0.2s;
      }

        nav > ul > li:hover > div {
          display: block;
          opacity: 1;
          visibility: visible;
        }

          nav > ul > li > div ul > li {
            display: block;
          }

            nav > ul > li > div ul > li > a {
              color: #fff;
              display: block;
              padding: 12px 24px;
              text-decoration: none;
            }

              nav > ul > li > div ul > li:hover > a {
                background-color: rgba( 255, 255, 255, 0.1);
              }
  
	

Update - Creating the Third Level Dropdown Menu

I've been asked by numerous people how to extend this tutorial to create a third level dropdown menu. Fortunately this is relatively easy and uses much of the same code as before.

Here's what the updated will do -

See the Pen lHoce by lawnch (@lawnch) on CodePen.

Creating the New Caret

As the current caret indicates a dropdown, we need to create a caret to indicate a sideways movement. This is done like so:

nav > ul > li > a > .caret,
nav > ul > li > div ul > li > a > .caret {
	border-top: 4px solid #aaa;
	border-right: 4px solid transparent;
	border-left: 4px solid transparent;
	content: "";
	display: inline-block;
	height: 0;
	width: 0;
	vertical-align: middle;

	-webkit-transition: color 0.1s linear;
	  -moz-transition: color 0.1s linear;
	-o-transition: color 0.1s linear;
	  transition: color 0.1s linear; 
  }
  
	nav > ul > li > div ul > li > a > .caret {
		border-bottom: 4px solid transparent;
		border-top: 4px solid transparent;
		border-right: 4px solid transparent;
		border-left: 4px solid #f2f2f2;
		margin: 0 0 0 8px;
	}
	

Importantly, we set the new caret to have identical styles to the downward one. Next we modify the direction it points through the use of transparent borders. To understand the different directions you can make the arrow point, I've discussed it earlier on.

3rd Layer Container

Similarly to the caret, we need to copy a previous style for the container and then modify it for the 3rd level.

nav > ul > li > div,
nav > ul > li > div ul > li > div {
	background-color: rgb( 40, 44, 47 );
	border-top: 0;
	border-radius: 0 0 4px 4px;
	box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.055);
	display: none;
	margin: 0;
	opacity: 0;
	position: absolute;
	width: 165px;
	visibility: hidden;
	
	-webkit-transiton: opacity 0.2s;
	-moz-transition: opacity 0.2s;
	-ms-transition: opacity 0.2s;
	-o-transition: opacity 0.2s;
	-transition: opacity 0.2s;
}

	nav > ul > li > div ul > li > div {
		border-radius: 0 4px 4px 4px;
		box-shadow: inset 2px 0 5px rgba(0,0,0,.15);
		margin-top: -42px;
		right: -165px;
	}
	
		nav > ul > li:hover > div,
		nav > ul > li > div ul > li:hover > div {
		  display: block;
		  opacity: 1;
		  visibility: visible;
		}
	

Let's deconstruct the second style definition in there:

  • border-radius: 0 4px 4px 4px; - this sets a 4px radius to all corners except the top left, which gives the box a good flow.
  • box-shadow - the shadow is set to run down the left side of the box, on the inside, making the box look below the second tier
  • margin-top - this pulls the box up so it's flush level with the container element
  • right - pulls the container right by 165px (the width of the second tier box)

The code - Three Tier CSS Navigation Menu

These are the two main changes from a two tier menu to a three tier. Below is the full code to use on your website:

HTML

Download here -

<nav>
	<ul>
		<li><a href="home.html">Home</a></li>
		<li>
      		<a href="products.html">Products <span class="caret"></span></a>
			<div>
				<ul>
					<li>
						<a href="products.html#chair">Chair <span class="caret"></span></a>
						<div>
							<ul>
								<li><a href="#">1</a></li>
								<li><a href="#">2</a></li>
								<li><a href="#">3</a></li>
								<li><a href="#">4</a></li>
								<li><a href="#">5</a></li>
							</ul>
						</div>
					</li>
					<li><a href="products.html#table">Table</a></li>
					<li><a href="cooker.html">Cooker</a></li>
				</ul>
			</div>
		</li>
		<li><a href="about.html">About</a></li>
		<li><a href="help.html">Help</a></li>
	</ul>
</nav>
	

CSS

Download here -

body {
  background-color: #EBE8E4;
  color: #222;
  font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif;
  font-weight: 300;
  font-size: 15px;
}

nav {
  background-color: #fff;
  border: 1px solid #dedede;
  border-radius: 4px;
  box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.055);
  color: #888;
  display: block;
  margin: 8px 22px 8px 22px;
  overflow: hidden;
  width: 90%; 
}

  nav ul {
    margin: 0;
    padding: 0;
  }

    nav ul li {
      display: inline-block;
      list-style-type: none;
      
      -webkit-transition: all 0.2s;
        -moz-transition: all 0.2s;
        -ms-transition: all 0.2s;
        -o-transition: all 0.2s;
        transition: all 0.2s; 
    }
      
      nav > ul > li > a > .caret,
	  nav > ul > li > div ul > li > a > .caret {
        border-top: 4px solid #aaa;
        border-right: 4px solid transparent;
        border-left: 4px solid transparent;
        content: "";
        display: inline-block;
        height: 0;
        width: 0;
        vertical-align: middle;
  
        -webkit-transition: color 0.1s linear;
     	  -moz-transition: color 0.1s linear;
       	-o-transition: color 0.1s linear;
          transition: color 0.1s linear; 
      }
	  
	  	nav > ul > li > div ul > li > a > .caret {
			border-bottom: 4px solid transparent;
			border-top: 4px solid transparent;
			border-right: 4px solid transparent;
			border-left: 4px solid #f2f2f2;
			margin: 0 0 0 8px;
		}

      nav > ul > li > a {
        color: #aaa;
        display: block;
        line-height: 56px;
        padding: 0 24px;
        text-decoration: none;
      }

        nav > ul > li:hover {
          background-color: rgb( 40, 44, 47 );
        }

        nav > ul > li:hover > a {
          color: rgb( 255, 255, 255 );
        }

        nav > ul > li:hover > a > .caret {
          border-top-color: rgb( 255, 255, 255 );
        }
		
		nav > ul > li > div ul > li:hover > a > .caret {
			border-left-color: rgb(255,255,255);
		}
      
      nav > ul > li > div,
	  nav > ul > li > div ul > li > div {
        background-color: rgb( 40, 44, 47 );
        border-top: 0;
        border-radius: 0 0 4px 4px;
        box-shadow: 0 2px 2px -1px rgba(0, 0, 0, 0.055);
        display: none;
        margin: 0;
        opacity: 0;
        position: absolute;
        width: 165px;
        visibility: hidden;
  
        -webkit-transiton: opacity 0.2s;
        -moz-transition: opacity 0.2s;
        -ms-transition: opacity 0.2s;
        -o-transition: opacity 0.2s;
        -transition: opacity 0.2s;
      }
	  
	  	nav > ul > li > div ul > li > div {
			background-color: rgb( 40, 44, 47 );
			border-radius: 0 4px 4px 4px;
			box-shadow: inset 2px 0 5px rgba(0,0,0,.15);
			margin-top: -42px;
			right: -165px;
		}

        nav > ul > li:hover > div,
		nav > ul > li > div ul > li:hover > div {
          display: block;
          opacity: 1;
          visibility: visible;
        }

          nav > ul > li > div ul > li,
		  nav > ul > li > div ul > li > div ul > li {
            display: block;
			position: relative;
          }

            nav > ul > li > div ul > li > a,
			nav > ul > li > div ul > li > div ul > li > a {
              color: #fff;
              display: block;
              padding: 12px 24px;
              text-decoration: none;
            }

              nav > ul > li > div ul > li:hover > a {
                background-color: rgba( 255, 255, 255, 0.1);
              }
	

Conclusion

Thanks for reading this tutorial, let me know what you come up with in the comments below.

If there are any web development subjects you want me to cover then feel free to contact me!

Advertisement
You may also like:
comments powered by Disqus