How to Build a Responsive Slide-Down Navigation Menu

After a long period of researching mobile responsive layouts, I’m spent quite a bit of time experimenting with various UI designs. One major hotspot on the page is often the website’s main navigation. Users want quick access to your content pages — and this will always be the case, either on a full monitor or a smaller mobile responsive screen.

For this tutorial I want to demonstrate how we can use a combination of CSS3 media queries along with some jQuery to manage a sliding navigation menu. The links will appear as normal on the frontend but drop into a hidden menu after resizing below 600px. Instead we see a little menu pull-down icon which will toggle open and closed on command.

Live DemoDownload Source Code

Setting the Document

The top heading area contains a small selection of files we need to create this effect. I am including a custom stylesheet along with a copy of the latest jQuery library hosted by Google. All of the custom JS functions are stored in an external file named menu.js.

<!doctype html>
<html lang="en-US">
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <title>Responsive Sliding Navigation Demo</title>
  <meta name="author" content="Jake Rocheleau">
  <link rel="shortcut icon" href="">
  <link rel="icon" href="">
  <link rel="stylesheet" type="text/css" media="all" href="styles.css">
  <link rel="stylesheet" type="text/css" media="all" href="">
  <script type="text/javascript" src=""></script>
  <script type="text/javascript" language="javascript" charset="utf-8" src="menu.js"></script>

Most of the page markup is fairly unimportant aside from the header area. I have attempted to keep everything at a fixed height, but the header cannot use a fixed CSS property or else the page won’t expand when sliding the menu open and closed. So the heading and navigation links are setup by line-height values in CSS.

  <header id="topnav">
	<li><a href="#" class="sel">Home</a></li>
	<li><a href="#">About</a></li>
	<li><a href="#">Projects</a></li>
	<li><a href="#">Blog</a></li>
	<li><a href="#">Get in Touch</a></li>
    <a href="#" id="navbtn">Nav Menu</a>        
    <h1><a href="#">Designee</a></h1>
  </header><!-- @end #topnav -->

The page h1 title fits best as the last element so the header will always keep its constant height. Right next to the headline is an anchor link with the ID #navbtn and this contains the sliding menu link icon. It will only display using CSS after the width drops below a certain threshold.

Markup Positions in CSS

Typically I do not consider even requiring jQuery whenever it is possible. The only problem with toggling menus is that we cannot do this efficiently in CSS. And the jQuery methods will apply inline CSS styles which overrule the default stylesheet. So it comes down to positioning the elements using CSS and helping them animate properly with JavaScript.

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, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
  outline: none;
  -webkit-font-smoothing: antialiased;
  -webkit-text-size-adjust: none;
  -ms-text-size-adjust: none;
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
html { height: 101%; }
body { 
  background: #f8f8f8 url('images/bg.png'); /* BG Neutral */
  font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
  font-size: 62.5%; 
  line-height: 1; 
  color: #343434;
  padding-bottom: 55px;

::selection { background: #b9e9b9; color: #555; }
::-moz-selection { background: #b9e9b9; color: #555; }
::-webkit-selection { background: #b9e9b9; color: #555; }

a { color: #6992c0; }
a:hover { color: #77a4dc; }

h2 { font-size: 2.9em; line-height: 1.4em; color: #626262; margin-bottom: 22px; }

p { font-size: 1.6em; line-height: 1.7em; color: #777; margin-bottom: 15px; }

#w {
  display: block;
  max-width: 900px;
  min-width: 300px;
  margin: 0 auto;

#content {
  margin: 0 1em;
  background: #fff;
  padding: 0 10px;

#pagebody {
  padding: 15px 25px;

My default CSS browser resets include a set of custom codes for the page typography. Also our body background tile is PS Neutral saved from Subtle Patterns. I had to split up the wrapper container and the body container into 2 divs because we are using side padding on the left and right to keep the page from growing to 100% width. Adding margin values onto the margin: 0 auto; property will result in losing the centered positioning.

/* navigation bar */
#topnav {
  display: block;
  width: 100%;
  position: relative;

#topnav #navbtn {
  display: none;
  float: right;
  top: 0;
  width: 20px;
  height: 70px;
  background: url('images/menu.png') center no-repeat;
  text-indent: -99999px;
  overflow: hidden;

#topnav nav {
  position: absolute;
  top: 0; 
  right: -10px;

#topnav nav ul {
  list-style: none;
#topnav nav ul li {
  display: block;
  float: left;
  font-size: 1.4em;
  margin-right: 4px;

#topnav nav ul li a {
  display: block;
  text-decoration: none;
  line-height: 70px;
  color: #8ea188;
  font-weight: bold;
  padding: 0 10px;
  border-bottom: 2px solid #fff;

#topnav nav ul li a:hover {
  color: #6f8767;
  background: #ddecd9;
  border-bottom-color: #bdd8b5;

By styling the inner