Get $500+ of the best After Effects files, video templates and music for only $20!
A Simple, Responsive, Mobile First Navigation

A Simple, Responsive, Mobile First Navigation

Tutorial Details
  • Topic: Responsive Web Design
  • Difficulty: Beginner
  • Estimated Completion Time: 15 mins

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.


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 navigation is placed at the top of a page, there’s a good chance it will obscure an entire mobile 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 Twitter’s 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

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.


Step 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.

<html lang="en">
<head>

	<meta charset="utf-8">
	<title>Mobile First Responsive Navigation</title>
	<meta name="description" content="CSS only mobile first navigation">
	<meta name="author" content="Ian Yates">

	<!--Mobile specific meta goodness :)-->
	<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

	<!--css-->
	<link rel="stylesheet" href="styles.css">

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

	<!-- Favicons-->
	<link rel="shortcut icon" href="img/favicon.ico">

</head>
<body id="home">

</body>
</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 :)

<body id="home">

	<div class="wrapper">

		<header>

			<h1 class="logo"><a href="">Nav</a></h1>

		</header>

		<article>

			<h2>Blue. No, yel&hellip;</h2> 

			<p>Shut up! Will you shut up?! But you are dressed as one&hellip; Camelot! You don't vote for kings.</p> 

		</article>

		<article>

			<h2>We want a shrubbery!!</h2> 

			<p>Look, my liege! Shut up! But you are dressed as one&hellip;</p> 

			<ul>
				<li>The nose?</li>
				<li>Shh! Knights, I bid you welcome to your new home. Let us ride to Camelot!</li>
				<li>Look, my liege!</li>
			</ul> 

		</article>

		<article>

			<h2>Help, help, I'm being repressed!</h2> 

			<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> 

		</article>

		<footer>

			<p>Copyright &copy;2012 Ian Yates <a href="http://webdesign.tutsplus.com">Webdesigntuts+</a></p>

		</footer>

	</div><!--end wrapper-->

</body>

Step 2: Navigation Markup

We’ve pulled together a basic html page, so now it’s time for the main attraction; our primary navigation..

		<nav id="primary_nav">

			<ul>

				<li><a href="">Portfolio</a></li>

				<li><a href="">About Me</a></li>

				<li><a href="">Nonsense</a></li>

				<li><a href="">Services</a></li>

				<li><a href="">Contact</a></li>

				<li><a href="#home">Top</a></li>

			</ul>

		</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.

		<header>

			<h1 class="logo"><a href="">Nav</a></h1>

			<a class="to_nav" href="#primary_nav">Menu</a>

		</header>

Step 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:

/* http://meyerweb.com/eric/tools/css/reset/
   v2.0b1 | 201101
   NOTE: WORK IN PROGRESS
   USE WITH CAUTION AND TEST WITH ABANDON */

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, figcaption, figure,
footer, header, hgroup, menu, nav, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	outline: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
	display: block;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}

/* remember to highlight inserts somehow! */
ins {
	text-decoration: none;
}
del {
	text-decoration: line-through;
}

table {
	border-collapse: collapse;
	border-spacing: 0;
}

Step 4: Basic Styles

At the moment our page is looking pretty uninspiring..

..so let’s improve things by adding some simple styling.

/*begin our styles*/

body {
	font: 16px/1.4em 'PT Sans', sans-serif;;
	color: #1c1c1c;
}

p,
ul {
	margin: 0 0 1.5em;
}

ul {
	list-style: disc;
	padding: 0 0 0 20px;
}

a {
	color: #1D745A;
}

h1 {

}

h2 {
	font-family: 'PT Serif', serif;
	font-size: 32px;
	line-height: 1.4em;
	margin: 0 0 .4em;
	font-weight: bold;
}

/*layout*/

.wrapper {
}

article {
	border-bottom: 1px solid #d8d8d8;
	padding: 10px 20px 0 20px;
	margin: 10px 0;
}

/*header*/

header {
	background: #1c1c1c;
	padding: 15px 20px;
}

		/*shorter clearfix http://nicolasgallagher.com/micro-clearfix-hack/*/
		header:before,
		header:after {
		    content:"";
		    display:table;
		}

		header:after {
		    clear:both;
		}

		/* For IE 6/7 (trigger hasLayout) */
		header {
		    zoom:1;
		}

h1.logo a {
	color: #d8d8d8;
	text-decoration: none;
	font-weight: bold;
	text-transform: uppercase;
	font-size: 20px;
	line-height: 22px;
	float: left;
	letter-spacing: 0.2em;
}

a.to_nav {
	float: right;
	color: #fff;
	background: #4e4e4e;
	text-decoration: none;
	padding: 0 10px;
	font-size: 12px;
	font-weight: bold;
	line-height: 22px;
	height: 22px;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	-webkit-border-radius: 2px;
	-moz-border-radius: 2px;
	border-radius: 2px;
}

a.to_nav:hover,
a.to_nav:focus {
	color: #1c1c1c;
	background: #ccc;
}

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.


Step 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..

/*navigation*/	

#primary_nav ul {
	list-style: none;
	background: #1c1c1c;
	padding: 5px 0;
}

#primary_nav li a {
	display: block;
	padding: 0 20px;
	color: #fff;
	text-decoration: none;
	font-weight: bold;
	text-transform: uppercase;
	letter-spacing: 0.1em;
	letter-spacing: 0.1em;
	line-height: 2em;
	height: 2em;
	border-bottom: 1px solid #383838;
}

#primary_nav li:last-child a {
	border-bottom: none;
}

#primary_nav li a:hover,
#primary_nav li a:focus {
	color: #1c1c1c;
	background: #ccc;
}

/*footer*/

footer {
	font-family: 'PT Serif', serif;
	font-style: italic;
	text-align: center;
	font-size: 14px;
}

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.


Step 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:

/*media queries*/

		@media only screen and (min-width: 768px) {

		}

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:

		@media only screen and (min-width: 768px) {

			a.to_nav {
				display: none;
			}

		}

With the browser made slightly wider, the menu button is no longer displayed.


Step 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.

		@media only screen and (min-width: 768px) {

			a.to_nav {
				display: none;
			}

			.wrapper {
				position: relative;
				width: 768px;
				margin: auto;
			}

			#primary_nav {
				position: absolute;
				top: 5px;
				right: 10px;
				background: none;
			}

			#primary_nav li {
				display: inline;
			}

			#primary_nav li a {
				float: left;
				border: none;
				padding: 0 10px;
				-webkit-border-radius: 2px;
				-moz-border-radius: 2px;
				border-radius: 2px;
			}

		}

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.


Step 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:

				<li class="top"><a href="#home">Top</a></li>

And then we can get rid of it within our media query:

			#primary_nav li.top {
				display: none;
			}

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, responsive, touch-friendly 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:

Add Comment

Discussion 27 Comments

  1. Very nice! Smashing Magazine has one of the best I’ve see thus far, 4 different layouts!

    http://www.smashingmagazine.com/

  2. Paul says:

    is this still usable on very long pages? does clicking on a link in the footer cause the whole page to scroll up? I don’t have a smartphone to test it

  3. jm2c says:

    Very simple, but awsome

  4. matt says:

    This is a nice and simple approach. Awesome. Thanks…

  5. This is great , Thanks :)

  6. Ed says:

    This is not an ideal solution if you need to think about accessibility. Placing the menu at the bottom can be a real pain for those navigating with text browsers and screen readers.

    • Adam says:

      I would replace “if” with “because”. There’s no “if” in accessibility…

      That said, those of us who use ATs tend to access content via the heading hierarchy and/or landmarks and access navigation via shortcuts and/or lists of links. So for us, this is not a big problem. We have many much bigger problems that occur time and again.

      It would be a bigger problem for any sighted users who cannot use pointing devices. For them, there needs to be a logical tab order and ways to to skip through/past/to major sections. An example of a thoroughly screwed up tab order is this website, actually. It goes to the comment form first.

    • Brett Lee says:

      Since we’re now putting content first instead of navigation first, couldn’t we have a “skip to navigation” jumps for accessibility concerns, much like we used to put in “skip to content” jumps? It wouldn’t be too much of a paradigm shift, since we’re really only doing things we used to do only with content and navigation in opposite places.

  7. Zbysek says:

    Great approach and thinking about mobile overall.

    I have question about accessibility though. How about people with screen readers? Is it ok to have navigation at the very bottom of the page? Does the link “to_nav” do the job if I use screen reader? Has anyone tested this approach considering screen readers?

    • Ian Yates says:
      Author

      Thanks Zbysek (and Ed) accessibility is a great issue to raise. Screen readers will read the content of a page in top-to-bottom order, so they’ll only come across the navigation after having trawled the rest of the document.

      However, there is a link to take you to the primary navigation and screen readers will read it effectively as long as the text within it is accurate. Ours reads “menu”, but could just as easily read “primary navigation” for example. Perhaps in that case image replacement would be a good idea, swapping that long label for the list icon.

      Arguably, we’ve served users with accessibility issues well; they no longer need to hop every single navigation link before reaching the actual content, and can still jump to the nav if they want to.

      • Jarrod says:

        You account for accessibility well, as long as the menu/primary navigation button is shown, but as soon as you hit the 768px width and the media query sets the link to ‘display:none;’, text browsers and screen readers will no longer see the link, and have to trawl the entire page’s content to find the navigation at the bottom.

        • Ian Yates says:
          Author

          Good point Jarrod! In that case, it’s probably best to hide the menu link using another method. display: none will (in most cases) hide it from browsers and screen readers, so it would be better to use position: absolute; left: -9999% and position it way off screen instead.

          Thanks for your input :)

  8. Hamid says:

    OMG!! very usefull Especially vewiport meta code on it!, Thq really keep it up m8.

  9. Fine tutorial indeed.

    Have made this navigation mistake on my site too with the “mobile” view having the nav at the top. I’ll have to rectify in the coming days.

  10. Varemenos says:

    Very nice, im already using this approach but why did you place the navigation at the button?

  11. Jeff Bach says:

    Great tutorial! Love the notion of designing for mobile first. But it is still bleeding edge. Old IE still dominates, at least in my part of the planet. Too bad MSFT IE remains the way they are……

    Sadly – I’ve got too many clients that just aren’t ready or even aware of mobile possibilities. Their clients are even further behind. (think midwest USA independent insurance agencies or at least some of them)

    If I can figure out a conditional comment that basically says “if the browser is any version of IE then go to a whole separate site….then this will be complete……

    • Ian Yates says:
      Author

      Glad you liked it Jeff :)

      This approach delivers to older IE browsers pretty well actually, serving them what is essentially a minimalised mobile version (read this).

      A conditional comment which then redirects the user to an IE specific site is possible, but opens up a whole can o’ worms in terms of reliability and maintenance (so don’t do it).

      As Brad Frost so eloquently put it: “Think of your core content as a fluid thing that gets poured into a huge number of containers.” Even though we’re dealing with uncooperative browsers, make sure your content can be ‘poured into’ them and accessed, then the battle’s won..

      • Jeff Bach says:

        I know that and you know that and everyone reading this probably knows that :) It is the way to go

        but…..the heart of it is getting my client comfortable with this new style of thinking and then recognizing that the biggest subset of his clients are still coming to his site on an old IE browser.

        It’s like torture getting excited about a spiff new toy and then not being able to play with it everywhere you go…..

  12. Jeff Bach says:

    Ian

    Can you state that assets listed only in a media query are ONLY loaded when that query is called?

    In your tutorial the mobile assets are loaded by default. If it is a mobile device that’s it? Nothing in the media query made for use when a large screen is “detected” is loaded?

    I’ve read through numerous different articles and seem to derive a different answer each time as to whether or not assets in a media query are loaded regardless or only when called.

    • Ian Yates says:
      Author

      That’s a good question Jeff, and the answer is yes, as far as I’m aware. I say as far as I’m aware because some bright spark will usually pipe up in the comments with an obscure exception, but we can safely assume that all modern and mobile browsers, which support media queries, handle them in the same way.

      Media queries work by loading assets only when their criteria is met. Check out this screenshot of our demo in action. I’ve altered the media queries so that an additional image is loaded as a background for larger screens. In Chrome, Firefox and Safari you’ll see that the image file is only loaded once the browser is stretched to within the range of the query.

      Bear in mind that browsers which don’t support media queries (< IE9) will read the contents of all media queries and therefore load everything, unless the only keyword is used.

      Hope that helps!

  13. Jered says:

    So I was thinking about this technique, shouldn’t it be the other way around? And with that I mean positioning the menu absolute at the bottom but it appears first in source order?

    • Ian Yates says:
      Author

      Hi Jered, good point, well made :)

      You certainly could do things that way and it would benefit you by having the nav markup near the top of the source code.

      Personally, I like the idea of having navigation at the end of the source code, as it means screen readers aren’t obliged to read each link before reaching any valuable content. As long as they can skip to the navigation, using a link which is at the top somewhere, you’re covered.

      Also (and this is pretty minor) if you’re positioning the nav at the bottom, you’ll have to make sure there’s a suitable gap at the bottom of the page where the nav will sit. The height of this gap would have to be entered manually and wouldn’t grow if more nav items are added. You could use a MASSIVE gap which places the nav way below the content, or even use JavaScript to calculate the necessary height, but that starts to miss the point..

      Anyway, nit-picking there, but yours is a good point, thanks :)

  14. Marco Salatin says:

    Hi there,

    Is there any solution which has “same” effect of responsive menu like the twitter bootstrap, but not using their source code?

    Thanks

Add a Comment