Responsive drop-down navigation

Are you in need of multi-level navigation? And that too responsive which fits well in all devices? In most cases, you design a drop-down menu using unordered  lists. But what do you do to make it usable on small and/or cursor less screens?

I have been successfully implementing it into my projects as there is no room for one-sided techniques anymore.

The technique consists of three main parts:

  1. Simple drop-down navigation based on HTML and CSS;
  2. Responsive implementation using media queries;
  3. Adoption for touch screen devices with the help of a super tiny jQuery plugin.


Now about everything in turn…

The Markup

On larger screens, show a horizontal drop-down menu, with up to 2 levels of sub-menus that appear when parent element is hovered over. On smaller screens, a “menu” button which displays our menu vertically, displaying sub-menus when parent element is clicked/touched.

<div class=”container”>
<a class=”toggleMenu” href=”#”>Menu</a>
<ul>
<li><a href=”#”>Home</a></li>
<li><a href=”#”>Microsoft</a>
<ul>
<li><a href=”#”>Products</a>
<ul>
<li><a href=”#”>Windows 8</a></li>
<li><a href=”#”>Outlook</a></li>
<li><a href=”#”>IE</a></li>
</ul>
</li>
<li><a href=”#”>Downloads</a></li>
</ul>
</li>
<li><a href=”#”>Apple</a>
<ul>
<li><a href=”#”>Mac</a></li>
<li><a href=”#”>iPhone</a></li>
<li><a href=”#”>iPad</a></li>
<li><a href=”#”>iPod</a></li>
<li><a href=”#”>iTunes</a></li>
</ul>
</li>
<li><a href=”#”>Articles</a></li>
<li><a href=”#”>Contact Us</a></li>
</ul>
</div>

Basic Styling

Let’s add some very basic styling to get our list looking like a navigation bar:

@import url(http://fonts.googleapis.com/css?family=Roboto+Slab);

body, nav, ul, li, a  {margin: 0; padding: 0;}
body { background-color:#e5e5e5; font-family: 'Roboto Slab', serif;}
a {text-decoration: none;}
.container { width: 90%; max-width: 700px; margin: 10px auto;}
.toggleMenu { display:  none; background: #1472c2; padding: 10px 15px; color: #fff;}
.nav { list-style: none; *zoom: 1; background:#1472c2; border:1px solid #fff; border-radius:5px;}
.nav:before, .nav:after { content: " "; display: table; }
.nav:after { clear: both;}
.nav ul { list-style: none; width: 9em;    float:left; left:50%; position:relative;}
.nav a { padding: 10px 15px; color:#fff;}
.nav li { position: relative; border-right:1px solid #1883dd; padding:0 15px 0 10px;}
.nav > li { float: left; border-top: 1px solid #1165ac;}
.nav > li > .parent { background-image: url("images/downArrow.png"); background-repeat: no-repeat; background-position: right;}
.nav > li > a { display: block;}
.nav li  ul { position: absolute; left: -9999px;}
.nav > li.hover > ul { left: 0;}
.nav li li.hover ul { left: 100%; top: 0;}
.nav li li{ padding:0;}
.nav li li a { display: block; background: #1577cb; position: relative; z-index:100; border-top: 1px solid #1165ac;}
.nav li li li a { background:#167fd8; z-index:200; border-top: 1px solid #1165ac;}

Lets put some responsiveness

@media screen and (max-width: 768px) {
 
.active { display: block; }
.nav > li { float: none; border-top: 1px solid #146eba; }
.nav > li > .parent { background-position: 95% 50%; }
.nav li li .parent { background-image: url(images/downArrow.png); background-repeat: no-repeat; background-position: 95% 50%; }
.nav ul { display: block; width: 100%; }
.nav > li.hover > ul , .nav li li.hover ul { position: static; }
}

Scripts for toggle menu, converting hover to click

var ww = document.body.clientWidth;
 
$(document).ready(function() {
 $(".nav li a").each(function() {
 if ($(this).next().length &gt; 0) {
 $(this).addClass("parent");
 };
 })
$(".toggleMenu").click(function(e) {
 e.preventDefault();
 $(this).toggleClass("active");
 $(".nav").toggle();
 });
 adjustMenu();
 })
$(window).bind('resize orientationchange', function() {
 ww = document.body.clientWidth;
 adjustMenu();
 });
var adjustMenu = function() {
 if (ww &lt; 768) {  $(".toggleMenu").css("display", "inline-block");  if (!$(".toggleMenu").hasClass("active")) {  $(".nav").hide();  } else {  $(".nav").show();  }  $(".nav li").unbind('mouseenter mouseleave');  $(".nav li a.parent").unbind('click').bind('click', function(e) {  // must be attached to anchor element to prevent bubbling  e.preventDefault();  $(this).parent("li").toggleClass("hover");  });  }  else if (ww &gt;= 768) {
 $(".toggleMenu").css("display", "none");
 $(".nav").show();
 $(".nav li").removeClass("hover");
 $(".nav li a").unbind('click');
 $(".nav li").unbind('mouseenter mouseleave').bind('mouseenter mouseleave', function() {
 // must be attached to li so that mouseleave is not triggered when hover over submenu
 $(this).toggleClass('hover');
 });
 }
 }

This is it! Complete fulfillment, full code and working example – all in the Demo / Download:

Final Words

I have run tests on the latest Chrome, Safari, Firefox and Opera browsers. Worked everywhere as it should.

Leave a Reply

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