A Simple, Responsive, Mobile First Navigation
We’re going to build a simple, responsive web site navigation. Our solution will help us place emphasis on the content of our page, arguably the top priority when designing for mobile. There’ll be no JavaScript involved, and we’ll tackle it from a Mobile First approach.
What is Mobile Navigation?
If you’ve read Luke Wroblewski’s Mobile First you’ll be familiar with his statement that:
“As a general rule, content takes precedence over navigation on mobile.”
What he means by this is that mobile users are often looking for immediate answers; they want the content they went searching for, not more navigation options.
Many sites, even responsive ones, stick to the convention that navigation belongs at the top of any given page. This approach can cause usability problems on mobile devices because mobile users are often short of two things: screen space and time. If primary mobile navigation is placed at the top of a page, there’s a good chance it will obscure an entire screen.
This issue is exacerbated further by large touch-friendly menu links, forcing users to scroll beyond the navigation to get to any valuable content.
Take this example from London & Partners:

A perfectly decent responsive design, but at standard mobile viewport dimensions (320px x 480px) all you really see is a navigation menu. Surely, having just arrived at the homepage, I want to see something other than that? It’s not just London & Partners who demonstrate this; it’s a practice seen in many responsive designs across the web.
So, What Are the Solutions?
We’ve seen a few ways of getting round this, often leaning on jQuery to sort things out for us. Take Chris Coyier’s explanation of the Five Simple Steps responsive dropdown menu.



Big screen, little screen.
Using jQuery, a duplicate of the menu is created in the form of a <select>
dropdown, initially hidden from view using CSS. When media queries detect a smaller screen, they make the dropdown visible and the original navigation invisible. This is perfect for mobile devices as dropdowns take up minimal real estate and make use of the device’s particular UI (like the iPhone’s scroller).
Alternatively, you might hide your navigation, but have it transition into view when a menu button is clicked. You can see this effect in action with the latest Bootstrap.



Smaller screens hide the navigation links and display a ’list’ icon (fast becoming accepted as meaning ’menu’) which reveals the navigation when clicked. Again, mobile visitors are presented with as much content as possible, but have navigation options available should they want them.



Pure CSS Solution to Mobile Navigation
We’re going to use a technique discussed by Luke, which makes use of CSS and a Mobile First approach. What do we mean by a Mobile First approach? Put simply, we’re going to design a straight-forward mobile layout, then progressively enhance the design for larger screens. We’ll use media queries which detect steadily increasing screen sizes, adding style and features as we go.
This means that only the bear minimum of CSS and resources will be loaded when our design is viewed with a mobile device. It also means that older versions of IE (which don’t recognize media queries) will be presented with the mobile site. Check out Joni Korpi’s Leaving Old Internet Explorer Behind for more information on this.
1. Markup
I’ll explain the ideas behind this solution as we go along, so for the time being let’s throw together some markup, starting off with a blanco HTML5 document.
1 |
<html lang="en"> |
2 |
<head>
|
3 |
|
4 |
<meta charset="utf-8"> |
5 |
<title>Mobile First Responsive Navigation</title> |
6 |
<meta name="description" content="CSS only mobile first navigation"> |
7 |
<meta name="author" content="Ian Yates"> |
8 |
|
9 |
<!--Mobile specific meta goodness :)-->
|
10 |
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> |
11 |
|
12 |
<!--css-->
|
13 |
<link rel="stylesheet" href="styles.css"> |
14 |
|
15 |
<!--[if lt IE 9]>
|
16 |
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
|
17 |
<![endif]-->
|
18 |
|
19 |
<!-- Favicons-->
|
20 |
<link rel="shortcut icon" href="img/favicon.ico"> |
21 |
|
22 |
</head>
|
23 |
<body id="home"> |
24 |
|
25 |
|
26 |
</body>
|
27 |
</html>
|
Note: Don’t Forget the Viewport Meta Tag!
Having done that, we’ll add some page structure. Straight-forward stuff and all for the purposes of our demonstration. I’ve used filler text from Monty Python’s Holy Grail (thanks Chris Valleskey) which is a nice way to put a smile on your face whilst you’re working :)
1 |
<body id="home"> |
2 |
|
3 |
<div class="wrapper"> |
4 |
|
5 |
<header>
|
6 |
|
7 |
<h1 class="logo"><a href="">Nav</a></h1> |
8 |
|
9 |
</header>
|
10 |
|
11 |
<article>
|
12 |
|
13 |
<h2>Blue. No, yel…</h2> |
14 |
|
15 |
<p>Shut up! Will you shut up?! But you are dressed as one… Camelot! You don’t vote for kings.</p> |
16 |
|
17 |
</article>
|
18 |
|
19 |
<article>
|
20 |
|
21 |
<h2>We want a shrubbery!!</h2> |
22 |
|
23 |
<p>Look, my liege! Shut up! But you are dressed as one…</p> |
24 |
|
25 |
<ul>
|
26 |
<li>The nose?</li> |
27 |
<li>Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot!</li> |
28 |
<li>Look, my liege!</li> |
29 |
</ul>
|
30 |
|
31 |
</article>
|
32 |
|
33 |
<article>
|
34 |
|
35 |
<h2>Help, help, I’m being repressed!</h2> |
36 |
|
37 |
<p>Why? Listen. Strange women lying in ponds distributing swords is no basis for a system of government. Supreme executive power derives from a mandate from the masses, not from some farcical aquatic ceremony. Be quiet! A newt?</p> |
38 |
|
39 |
</article>
|
40 |
|
41 |
<footer>
|
42 |
|
43 |
<p>Copyright ©2012 Ian Yates <a href="http://webdesign.tutsplus.com">Webdesigntuts+</a></p> |
44 |
|
45 |
</footer>
|
46 |
|
47 |
</div><!--end wrapper--> |
48 |
|
49 |
</body>
|
2. Navigation Markup
We’ve pulled together a basic html page, so now it’s time for the main attraction; our primary navigation..
1 |
|
2 |
<nav id="primary_nav"> |
3 |
|
4 |
<ul>
|
5 |
|
6 |
<li><a href="">Portfolio</a></li> |
7 |
|
8 |
<li><a href="">About Me</a></li> |
9 |
|
10 |
<li><a href="">Nonsense</a></li> |
11 |
|
12 |
<li><a href="">Services</a></li> |
13 |
|
14 |
<li><a href="">Contact</a></li> |
15 |
|
16 |
<li><a href="#home">Top</a></li> |
17 |
|
18 |
</ul>
|
19 |
|
20 |
</nav><!--end primary_nav--> |
Yes, you’ve seen that correctly, we’ve added that at line 68, after the last article. Don’t forget that we’re designing for mobile now, we’ll cover desktop later. We’ve placed the navigation at the bottom of our page so that it’s completely out of the way. We’re now going to place a link at the top of our page so that users can find the navigation if they wish.
1 |
|
2 |
<header>
|
3 |
|
4 |
<h1 class="logo"><a href="">Nav</a></h1> |
5 |
|
6 |
<a class="to_nav" href="#primary_nav">Menu</a> |
7 |
|
8 |
</header>
|
3. CSS Reset
Depending on how you normally begin web projects, this step my differ from your usual workflow. I’ve always found Eric Meyer’s reset to be a solid basis to work from, especially as he’s tweaked it recently. We’ll add his reset rules to a stylesheet to kick our css off:
1 |
/* http://meyerweb.com/eric/tools/css/reset/
|
2 |
v2.0b1 | 201101
|
3 |
NOTE: WORK IN PROGRESS
|
4 |
USE WITH CAUTION AND TEST WITH ABANDON */
|
5 |
|
6 |
html, body, div, span, applet, object, iframe, |
7 |
h1, h2, h3, h4, h5, h6, p, blockquote, pre, |
8 |
a, abbr, acronym, address, big, cite, code, |
9 |
del, dfn, em, img, ins, kbd, q, s, samp, |
10 |
small, strike, strong, sub, sup, tt, var, |
11 |
b, u, i, center, |
12 |
dl, dt, dd, ol, ul, li, |
13 |
fieldset, form, label, legend, |
14 |
table, caption, tbody, tfoot, thead, tr, th, td, |
15 |
article, aside, canvas, details, figcaption, figure, |
16 |
footer, header, hgroup, menu, nav, section, summary, |
17 |
time, mark, audio, video { |
18 |
margin: 0; |
19 |
padding: 0; |
20 |
border: 0; |
21 |
outline: 0; |
22 |
font-size: 100%; |
23 |
font: inherit; |
24 |
vertical-align: baseline; |
25 |
}
|
26 |
/* HTML5 display-role reset for older browsers */
|
27 |
article, aside, details, figcaption, figure, |
28 |
footer, header, hgroup, menu, nav, section { |
29 |
display: block; |
30 |
}
|
31 |
body { |
32 |
line-height: 1; |
33 |
}
|
34 |
ol, ul { |
35 |
list-style: none; |
36 |
}
|
37 |
blockquote, q { |
38 |
quotes: none; |
39 |
}
|
40 |
blockquote:before, blockquote:after, |
41 |
q:before, q:after { |
42 |
content: ’’; |
43 |
content: none; |
44 |
}
|
45 |
|
46 |
/* remember to highlight inserts somehow! */
|
47 |
ins { |
48 |
text-decoration: none; |
49 |
}
|
50 |
del { |
51 |
text-decoration: line-through; |
52 |
}
|
53 |
|
54 |
table { |
55 |
border-collapse: collapse; |
56 |
border-spacing: 0; |
57 |
}
|
4. Basic Styles
At the moment our page is looking pretty uninspiring..



..so let’s improve things by adding some simple styling.
1 |
/*begin our styles*/
|
2 |
|
3 |
body { |
4 |
font: 16px/1.4em ’PT Sans’, sans-serif;; |
5 |
color: #1c1c1c; |
6 |
}
|
7 |
|
8 |
p, |
9 |
ul { |
10 |
margin: 0 0 1.5em; |
11 |
}
|
12 |
|
13 |
ul { |
14 |
list-style: disc; |
15 |
padding: 0 0 0 20px; |
16 |
}
|
17 |
|
18 |
a { |
19 |
color: #1D745A; |
20 |
}
|
21 |
|
22 |
h1 { |
23 |
|
24 |
}
|
25 |
|
26 |
h2 { |
27 |
font-family: ’PT Serif’, serif; |
28 |
font-size: 32px; |
29 |
line-height: 1.4em; |
30 |
margin: 0 0 .4em; |
31 |
font-weight: bold; |
32 |
}
|
33 |
|
34 |
/*layout*/
|
35 |
|
36 |
.wrapper { |
37 |
}
|
38 |
|
39 |
article { |
40 |
border-bottom: 1px solid #d8d8d8; |
41 |
padding: 10px 20px 0 20px; |
42 |
margin: 10px 0; |
43 |
}
|
44 |
|
45 |
/*header*/
|
46 |
|
47 |
header { |
48 |
background: #1c1c1c; |
49 |
padding: 15px 20px; |
50 |
}
|
51 |
|
52 |
/*shorter clearfix http://nicolasgallagher.com/micro-clearfix-hack/*/
|
53 |
header:before, |
54 |
header:after { |
55 |
content:""; |
56 |
display:table; |
57 |
}
|
58 |
|
59 |
header:after { |
60 |
clear:both; |
61 |
}
|
62 |
|
63 |
/* For IE 6/7 (trigger hasLayout) */
|
64 |
header { |
65 |
zoom:1; |
66 |
}
|
67 |
|
68 |
h1.logo a { |
69 |
color: #d8d8d8; |
70 |
text-decoration: none; |
71 |
font-weight: bold; |
72 |
text-transform: uppercase; |
73 |
font-size: 20px; |
74 |
line-height: 22px; |
75 |
float: left; |
76 |
letter-spacing: 0.2em; |
77 |
}
|
78 |
|
79 |
a.to_nav { |
80 |
float: right; |
81 |
color: #fff; |
82 |
background: #4e4e4e; |
83 |
text-decoration: none; |
84 |
padding: 0 10px; |
85 |
font-size: 12px; |
86 |
font-weight: bold; |
87 |
line-height: 22px; |
88 |
height: 22px; |
89 |
text-transform: uppercase; |
90 |
letter-spacing: 0.1em; |
91 |
-webkit-border-radius: 2px; |
92 |
-moz-border-radius: 2px; |
93 |
border-radius: 2px; |
94 |
}
|
95 |
|
96 |
a.to_nav:hover, |
97 |
a.to_nav:focus { |
98 |
color: #1c1c1c; |
99 |
background: #ccc; |
100 |
}
|
This is all basic stuff (fonts, line-heights, colors etc.), what’s crucial so far is that I’ve styled the ’menu’ button to float to the right within the <header>
, where you’d often expect navigation to be found.



If you hover over it you’ll see the hover state - not necessary for touch screen devices of course, but this experience will also be delivered to uncooperative Internet Explorer versions. What we have defined for the benefit of mobile users is a :focus
state. It’s the same as the :hover
state, but will offer crucial feedback for touch-screen devices. Our users will know they’ve been successful in touching the menu button.
Anyway, click it and you’ll be taken to the navigation, super.



Now let’s style the menu a bit.
5. Navigation Styles
We’re actually going to style our primary navigation much like the London & Partners example shown earlier on, except this time it’s obviously at the bottom of the page..
1 |
/*navigation*/
|
2 |
|
3 |
#primary_nav ul { |
4 |
list-style: none; |
5 |
background: #1c1c1c; |
6 |
padding: 5px 0; |
7 |
}
|
8 |
|
9 |
#primary_nav li a { |
10 |
display: block; |
11 |
padding: 0 20px; |
12 |
color: #fff; |
13 |
text-decoration: none; |
14 |
font-weight: bold; |
15 |
text-transform: uppercase; |
16 |
letter-spacing: 0.1em; |
17 |
letter-spacing: 0.1em; |
18 |
line-height: 2em; |
19 |
height: 2em; |
20 |
border-bottom: 1px solid #383838; |
21 |
}
|
22 |
|
23 |
#primary_nav li:last-child a { |
24 |
border-bottom: none; |
25 |
}
|
26 |
|
27 |
#primary_nav li a:hover, |
28 |
#primary_nav li a:focus { |
29 |
color: #1c1c1c; |
30 |
background: #ccc; |
31 |
}
|
32 |
|
33 |
/*footer*/
|
34 |
|
35 |
footer { |
36 |
font-family: ’PT Serif’, serif; |
37 |
font-style: italic; |
38 |
text-align: center; |
39 |
font-size: 14px; |
40 |
}
|
Much better. We’ve made the menu links nice and large (read more about Touch Target Sizes on Luke Wroblewski’s own blog) and once again determined a :focus
state for user feedback.



It’s also become clear that we’ve included a ’top’ link which will take users back to the top of the page if needed.
6. Getting Bigger
OK, we’ve dealt with our simple mobile layout, so now it’s time for some progressive enhancement. We’re going to use media queries to determine when our mobile layout is no longer appropriate.
But at what point does it become inappropriate? There are many ways to approach media queries, but we’re going to work from the basis that a mobile viewport is 320px x 480px. It’s 320px wide when viewed in portrait, 480px wide when viewed in landscape, so we could justifiably set our first media query to detect any screen larger than 480px.
However, the next step up is arguably the tablet. The iPad has a resolution of 980px x 768px, so we can safely assume that anything smaller than 768px is appropriate for our mobile layout. Anything larger than 768px can handle more desktop-like navigation layouts.
We can therefore start adding rules, so let’s set up a media query:
1 |
/*media queries*/
|
2 |
|
3 |
@media only screen and (min-width: 768px) { |
4 |
|
5 |
}
|
This media query will run all styles contained within it when the viewport is at least 768px wide. Note the inclusion of the only keyword, which ensures Internet Explorer 8 doesn’t get all confused and try to process the query. See my earlier explanation for details.
Let’s kick things off by making our ’menu’ button disappear:
1 |
|
2 |
@media only screen and (min-width: 768px) { |
3 |
|
4 |
a.to_nav { |
5 |
display: none; |
6 |
}
|
7 |
|
8 |
}
|



With the browser made slightly wider, the menu button is no longer displayed.
7. Shifting the Navigation
Now we need to bring our primary navigation to the top of the page. We’ll do that by removing it from the document flow, positioning it absolutely at the top.
1 |
|
2 |
@media only screen and (min-width: 768px) { |
3 |
|
4 |
a.to_nav { |
5 |
display: none; |
6 |
}
|
7 |
|
8 |
.wrapper { |
9 |
position: relative; |
10 |
width: 768px; |
11 |
margin: auto; |
12 |
}
|
13 |
|
14 |
#primary_nav { |
15 |
position: absolute; |
16 |
top: 5px; |
17 |
right: 10px; |
18 |
background: none; |
19 |
}
|
20 |
|
21 |
#primary_nav li { |
22 |
display: inline; |
23 |
}
|
24 |
|
25 |
#primary_nav li a { |
26 |
float: left; |
27 |
border: none; |
28 |
padding: 0 10px; |
29 |
-webkit-border-radius: 2px; |
30 |
-moz-border-radius: 2px; |
31 |
border-radius: 2px; |
32 |
}
|
33 |
|
34 |
}
|
In order for that to be possible we first have to make its parent (.wrapper
) relatively positioned. We can either do that here in the media query, or determine that at the beginning of our stylesheet.
Once the menu is positioned absolutely, we need to remove some of the anchor styling. There’s not much to do, but we need the list items to display inline, and we need to remove the borders and exaggerated padding from the anchors. The hover states we dictated earlier are fine of course, so we needn’t change them.



8. One Last Thing
If you’ve been paying attention you’ll have noticed that we still have a ’top’ link in the navigation - we don’t really need that any more eh?
We can remove this in a number of ways, but so we’re sure of what’s going on let’s first add a class to the list item:
1 |
|
2 |
<li class="top"><a href="#home">Top</a></li> |
And then we can get rid of it within our media query:
1 |
|
2 |
#primary_nav li.top { |
3 |
display: none; |
4 |
}
|



Conclusion
That’s it! There are loads of ways to build upon this idea (implementing the list icon being just one) and, of course, you can continue to add media queries to cater for growing screens.
Hopefully you now have the foundations to do so. We’ve created a simple, touch-friendly, responsive navigation, from a mobile first approach whilst giving emphasis to content and usability. Who can ask for more?!
Further Resources
A few useful links mentioned in the tutorial, all piled into one handy list:
- Luke Wroblewski’s Mobile First
- Chris Coyier’s jQuery-based responsive dropdown menu
- Five Simple Steps
- Twitter Bootstrap
- Joni Korpi’s Leaving Old Internet Explorer Behind
- Don’t Forget the Viewport Meta Tag!
- Chris Valleskey’s Monty Python (amongst other things) filler text
- Eric Meyer’s reset revisited
- Luke Wroblewski’s Touch Target Sizes
- My explanation of the media query “only” keyword
- Brad Frost’s responsive navigation patterns
- Aaron Gustafson’s Build a smart mobile navigation without hacks on .net Magazine
Premium Option
There are plenty of mobile first design templates available on Envato Market for immediate use in your projects.


