Select Page

How to create a responsive navigation

Creating a simple responsive navigation using media queries and some JavaScript

Responsiveness is in the air…
Bet you’ve heard about responsive web design before. If you haven’t, go and read the article “Responsive Web Design” by Ethan Marcotte, I’ll wait….

Ok?

Now, I won’t be going over any “responsive design” or “mobile first” concepts here. There are enough great resources out there covering the topic to it’s core. But make sure you get yourself familiar with these topics, they’re a “must know” for every well-versed web designer.

 


 

So, today I will show you how to create a responsive navigation for your web project. What this means is, our website navigation is going to display differently depending on what size the screen of our device (mobile, desktop) has.

A small demonstration how this will look like:

 

see demo

 

You can even resize your browser window’s width (if you’re reading this article on a desktop screen) and you will see that this website too has a responsive navigation.

Ok, let’s get in there…

 


 

The HTML document

First (as usual ;-), we will start with the basic HTML document. If you need help on that, go and read my article “The basic HTML structure“. I’ve used the very same structure for my responsive navigation below.

<!DOCTYPE html>
<html lang=”en”>
<head>
    <meta charset="UTF-8">
    
    <title>The responsive navigation</title>
    
    <meta name="author" content="Jaime Butler">
    <meta name="description" content="....">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link href="style.css" rel="stylesheet">

    <!--[if lt IE 9]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->


    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

<head>
<body>

<!-- CONTENT -->

</body>
</html>

Now, you might have noticed the highlighted additions to what we had in our “Basic HTML structure”.

Let’s have a look at them:

 

The Viewport Meta Tag

<meta name="viewport" content="width=device-width, initial-scale=1">

This is the meta tag for the viewport (display area). It is used to tell the browser what viewport and which zoom level should be used when displaying the website on screens.

So in our viewport meta tag we are telling the browser to use the “width” of the device the website is currently displayed on with “content=”width=device-width,…”, and setting the initial zoom level to 1 with “…initial-scale=1″” (meaning 1 CSS pixel is equal to 1 viewport pixel).

If you want to know more about the viewport meta tag, there is a lot of information out on the web, or read this article on tutsplus.

But remember this: if your not design for responsive layout DON’T use the viewport meta tag!

 

The HTML5shiv/m

<!--[if lt IE 9]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->

The HTML5shiv (or HTML5shim, there both the same) is a simple JavaScript workaround letting you style certain HTML5 elements in older versions of IE.
Since we will be using the HTML5 elements “nav” and “header” on our document, we’re going to put this in place. We are only loading the JavaScript if IE is later then version 9.

 

jQuery

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

We are going to use some jQuery function for the toggling of our mobile navigation so we also include the jQuery library here (I tend to have my jQuery library as local resource, but here we are using Google CND).

Now we have the basic “infrastructure” in place, so we can start with the navigation bar.

 

The Navigation

First we’re going to add our navigation list into the body.
We will be using some new HTML5 tags to give our markup some structure.

Let’s look at the code and take it apart:

<body>
	<header>
		<nav>
			<ul>
				<li>
					<a href="#">Home</a>
				</li>
				<li>
					<a href="#">Work</a>
				</li>
				<li>
					<a href="#">Blog</a>
				</li>
				<li>
					<a href="#">About</a>
				</li>
			</ul>
		</nav>	
	</header>
</body>

 

The header tag

We have the “header” tag which is one of the new HTML5 structural elements wrapping around our navigation.
Why use the “header” tag?…well, because we have it ;-) As per definition the “header” tag should be used as container for introductory content or for navigational links. So that’s exactly what we have here. You don’t have to use the “header” tag (or any HTML5 elements), but get into the habit of using the HTML5 new structural elements today.

 

The nav tag

Also a new HTML5 structural element, the “nav” tag is intended to be used for major navigation links. The “nav” tag is great because it will be very useful for assistive technology, allowing screen reader users to skip past the navigation without having to provide a “skip navigation” link.

 

The list

We are using an unordered list (“ul”) containing our list elements (“li”) with the links (“a”) for our navigation. For me, using a list for navigation is the way to go.
Chris Coyier has publish a great article on the topic “Navigation in Lists: To Be or Not To Be”, go and check it out.

So how will this look so far:

Basic List

Well, this isn’t very “sexy”, is it. We just have a simple list of links. Ok let’s do some styling.

As you can see in the head of our document, we’re linking to an external style.css where we are going to place our styling.
So let’s start:

html, body {
	height: 100%;
	width:100%;
	padding:0;
	margin:0;
	font-family: Verdana, Arial, Helvetica, sans-serif;
	font-size: 100%;
}

a {
	text-decoration: none;
	color:#000000;
}

/* header */
header {width:95%;margin:0 auto;padding:1em 0;}

Here is some basic styling to start with. This won’t do all that much with our list. What we have on line 16 is the style for our header element. We are giving it some room setting the top and bottom padding and letting it have a width of 95%.

Ok, let’s get to the list:

/* Navigation */
nav {
	background-color:#497BAD;
	text-align:center;
}

nav ul {
	margin:0;
	padding:0;
	list-style:none;
}

nav ul li {
	border-bottom:1px solid #64A8ED;
}

nav > ul > li > a {
	display:block;
	text-decoration:none;
	padding: 1em 1.1em;
	color:#fff;
	font-size:0.9rem;
}

nav > ul > li.current-page,
nav > ul > li:hover {
	background-color:#64A8ED;
}

I’m going to go through all this CSS with you.

Lines- 18-21:
First we are simply giving our “nav” element a background color and align the text to center.

Lines 23-26:
Since the browser styles our “ul” element with these “disc” listings and adds some padding and margin, we’re going to remove all of this from our “ul” element which is inside the nav.

Line 30:
Next we’re going to add a border to the bottom of every “li” elements to separate our links visually.

Lines 33-39:
Here we’re grabbing our anchor links. First we set the display property to block. Since anchor tags are inline elements we manage to make the entire list element clickable and not only the text.
We remove the text decoration (default underline), give the element some padding, set the text color and define a specific font size.

Lines 41-44:
Finally we define a class “current-page” for our “li” elements. This will be set for the current page we are on. And we want our navigation links to change background when we hover over them.
So we give those two a different background color.

Now we can go back to our list in the HTML document and give the “Home” list element that defined class “current-page”:

<nav>
			<ul>
				<li class="current-page">
					<a href="#">Home</a>
				</li>
				<li>
					<a href="#">Work</a>
				</li>

Let’s check out how things are looking

Styled List

But wait…seams we have a vertical navigation now. This doesn’t look really “pretty” on our desktop, right.
Let’s reveal my thinking on this:

 

The “Mobile First” approach

What we are doing here is, we’re design our navigation for mobile first. This means, the default style of our navigation will be our “Mobile” version, and we’re going to layer on styles optimized for larger screen with media queries.
It’s much simpler and we won’t have to override our style for mobile later.

Luke Wroblewski wrote a nice brief book about the “Mobile First” approach.

 

The media queries

So let’s get things going with our media queries. I’m not going to go into media queries in detail here. If you want to know more check out this article about the media queries on CSS-Tricks.
But we’re going to be using the “min-width” media queries. This means we’re going to change styles as the viewport widens, so our styles in the media query will only apply if the minimum width of our screen is given.

Let’s add the media query to our CSS file:

/* Medium screens (640px) */
@media (min-width: 640px) {
	html { 
		font-size: 110%; 
	}
	
	nav ul li {
		display:inline-block; /* Stack the li elements inline */
		border-bottom:none; /* Remove Border */
	}
}

Here we have a media query targeting a minimum width of 640px. It is totally up to you what min-width you set to apply different style.
If you’re designing for a specific device, here is a huge list of device sizes so you can target the minimum width you’re after.

You can have as many media queries as you want. So you could define specific style that kick in when you have large viewports (like over 1024px).

So what are we doing when our viewport reaches a width over 640px?
First we increase the font size on the html element (just to visualize the change) and we’re overriding two properties of our navigation list element to get a horizontal navigation.
We’re displaying the list elements as inline-block (line 53) and removing the bottom border (line 54).

Go try resizing your browser and see the media query in action.

Width > 640px:

Desktop Nav List

Width < 640px:

Mobile Nav List

 

As you can see, with only one simple media query we manage to get a navigation that is mobile friendly and looks “classic” on desktop screens.

 

The mobile toggle menu

Now we have the styling in place and our media query firing when we need it, it’s time to turn our navigation into a toggle menu using some JavaScript.

We are going to need an additional link to make our menu visible when clicked, and some jQuery to get a nice toggle effect.

So let’s start with our additional link:

<header>
	<a href="#" id="mobile-nav">&#9776;</a>
		<nav>
			<ul>
				<li class="current-page">
					<a href="#">Home</a>
				</li>
				<li>
					<a href="#">Work</a>
				</li>
				<li>
					<a href="#">Blog</a>
				</li>
				<li>
					<a href="#">About</a>
				</li>
			</ul>
		</nav>		
	</header> 

We’re going the place a link with an id “mobile-nav” just above our “nav” element in the header (line 23).
The “#9776” is a Unicode symbol with three lines in it to represent the menu placeholder. There are several way’s to do this (icon, CSS or just text) but I’ll go with the Unicode.

We might want to do some styling on this link so add this to our CSS (I’ll place it just above our nav styles):

#mobile-nav {
	display:block;
	background-color:#497BAD;
	color:#000;
	font-size:1.2rem;
	padding:0.6em;
	text-align:right;
}

We’ll target the ID of the link we set (mobile-nav) and change the display property to “block” (as with the other links we can click the hole element now).
Giving it a background, font size, some padding and align it to the right so it looks “pretty” (bet you’ll do a better job in making your nav look “pretty” ;-).

 

Hiding what we don’t want

We now have this “three line” icon thing sitting on top of our navigation. We’re going to hide it when we have a viewport width more then 640px.

So we’re going to add this little snippet to our media query (highlighted):

@media (min-width: 640px) {
	html { 
		font-size: 110%; 
	}
	
	nav ul li {
		display:inline-block; /* Stack the li elements inline */
		border-bottom:none; /* Remove Border */
	}
	
	/* Remove Mobile Nav */
	#mobile-nav {
		display: none;
	}

} 

Notice when you resize the browser now we almost have what we’re after. The last thing to do in terms of styling is to hide the “mobile” nav, so it will only be shown when we click our menu placeholder.

So we hide the “nav” element completely by adding:

nav {
	display:none;
	background-color:#497BAD;
	text-align:center;
}

By doing this, we have one problem. Our “nav” is gone completely when on desktop view, so we have to add the display property to make it visible again when our media query fires:

@media (min-width: 640px) {
	html { 
		font-size: 110%; 
	}
	
	nav {
		display:block;
	}
	
	nav ul li {
		display:inline-block; /* Stack the li elements inline */
		border-bottom:none; /* Remove Border */
	}
	
	/* Remove Mobile Nav */
	#mobile-nav {
		display: none;
	}

} 

 

Adding the toggle effect

Upps…now our “mobile” navigation is gone, leaving us with just a link that doesn’t do anything (yet).

So let’s add a simple jQuery function, making our link toggle the menu as we click:

At the bottom of our HTML document just before the closing “body” tag we’re going to add this (Since this is JavaScript, we’re putting the function into the “script” tag):

....
<script>

function navMobile() {
    
    var menu= $("nav");
    var button= $("#mobile-nav");

    $(button).on("click",function(e) {
      e.preventDefault();
      menu.slideToggle();
    });

    $(window).resize(function(){  
      var w = $(window).width();  
      if(w > 640 && menu.is(':hidden')) {  
        menu.removeAttr('style');  
      }  
    }); 
  }
  $(function () {
    navMobile();
  });

</script>
....

Wow, looking kind of “freaky”. Let’s see what’s happening here:

First we create a function called “navMobile” (you can name it what ever you want).
In the function we create two variables with the values of 1. The “nav” element, 2. The “mobile-nav” link.

function navMobile() {
    
    var menu= $("nav");
    var button= $("#mobile-nav");

Then we’re hooking an on “click” event to the “button” (our link) element saying, “…when the element is clicked, do something”.

    $(button).on("click",function(e) {

Using the preventDefault() function we are stopping the link to follow the URL and then using the slideToggle() function from jQuery to do the “toggle” action on our “menu” variable.

      e.preventDefault();
      menu.slideToggle();
    });

However, if you open and close your menu, and then resize the browser to “desktop” view, the complete “nav” element will be set to “:hide” through our function.
So we need another function that removes this style from our element.

    $(window).resize(function(){  
      var w = $(window).width();  
      if(w > 640 && menu.is(':hidden')) {  
        menu.removeAttr('style');  
      }  
    }); 

Here we are using the .resize event on our window saying that, „if we resize the window…do something…“.
On line 55 we get the width of our window and store it in a variable.
Then we have a little „IF“ statement, where if the width of our window is greater then 640px (the width we defined in our media query) and our variable „menu“ (set at the beginning of our other function) has a style attribute „:hidden“, we remove the style attribute from our „nav“ element.

to finish things off, all we have to do is call our navMobile() at the bottom of the script

$(function () {
    navMobile();
});

 

Putting it together

so this was quite a bit of explaining…let‘s put the HTML document and the CSS together:

HTML:

<!DOCTYPE html>
<html lang=”en”>
<head>
    <meta charset="UTF-8">
     
    <title>The responsive navigation</title>
     
    <meta name="author" content="Jaime Butler">
    <meta name="description" content="....">
    <meta name="viewport" content="width=device-width, initial-scale=1">
 
    <link href="style.css" rel="stylesheet">
 
    <!--[if lt IE 9]>
    <script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
    <![endif]-->
 
 
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
 
<head>
<body>
 
<header>
    <a href="#" id="mobile-nav">&#9776;</a>
        <nav>
            <ul>
                <li class="current-page">
                    <a href="#">Home</a>
                </li>
                <li>
                    <a href="#">Work</a>
                </li>
                <li>
                    <a href="#">Blog</a>
                </li>
                <li>
                    <a href="#">About</a>
                </li>
            </ul>
        </nav>       
    </header> 
    <script>
 
function navMobile() {
     
    var menu= $("nav");
    var button= $("#mobile-nav");
 
    $(button).on("click",function(e) {
      e.preventDefault();
      menu.slideToggle();
    });
 
    $(window).resize(function(){ 
      var w = $(window).width(); 
      if(w > 640 && menu.is(':hidden')) { 
        menu.removeAttr('style'); 
      } 
    });
  }
  $(function () {
    navMobile();
  });
 
</script> 
</body>
</html>

CSS:

html, body {
    height: 100%;
    width:100%;
    padding:0;
    margin:0;
    font-family: Verdana, Arial, Helvetica, sans-serif;
    font-size: 100%;
}
 
a {
    text-decoration: none;
    color:#000000;
}
 
/* header */
header {width:95%;margin:0 auto;padding:1em 0;}

/* Navigation */

#mobile-nav {
    display:block;
    background-color:#497BAD;
    color:#000;
    font-size:1.2rem;
    padding:0.6em;
    text-align:right;
}

nav {
	display: none;
    background-color:#497BAD;
    text-align:center;
}
 
nav ul {
    margin:0;
    padding:0;
    list-style:none;
}
 
nav ul li {
    border-bottom:1px solid #64A8ED;
}
 
nav > ul > li > a {
    display:block;
    text-decoration:none;
    padding: 1em 1.1em;
    color:#fff;
    font-size:0.9rem;
}
 
nav > ul > li.current-page,
nav > ul > li:hover {
    background-color:#64A8ED;
}




@media (min-width: 640px) {
    html {
        font-size: 110%;
    }
     
    nav {
        display:block;
    }
     
    nav ul li {
        display:inline-block; /* Stack the li elements inline */
        border-bottom:none; /* Remove Border */
    }
     
    /* Remove Mobile Nav */
    #mobile-nav {
        display: none;
    }
 
} 

 


 

That’s it!
We have a responsive navigation with some user friendly toggle action when on small screens.
You can now play around with the styling, and add additional media queries to meet your needs.

Go ahead and try to be responsive in future projects. Get yourself comfortable with the concepts and maybe even try to apply the idea of „Mobile First“ when design for cross device compatibility.

Hope this was of any use for some of you…if it was or if you have any questions…drop me a line or leave a comment below

Jaime

Submit a Comment

Your email address will not be published. Required fields are marked *

eighteen − 8 =

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Pin It on Pinterest