Meta Q how to: Responsive toggle menus brought to you by META Q

Meta Q how to: Responsive toggle menus

I was recently tasked with building a responsive navigation menu for a project I was on working at Q Digital Studio. It works thusly: when the browser window is at mobile sizes, the navigation bar "magically" transforms into a dropdown list. You can view a demo of it here.

The specs were pretty straightforward:

  • At mobile sizes, the navigation should display as a drop down menu.

  • When the user taps the dropdown, the links should slide open.

  • At tablet sizes and up, the navigation should display as a horizontal bar.

Here's how we can make the magic happen.

First let's build out our navigation.

<nav class="group">
  <h2 class="navheader slide-trigger">Menu <span></span></h2>
  <ul class="navigation group">
    <li><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Team</a></li>
    <li><a href="#">Portfolio</a></li>
    <li><a href="#">Contact</a></li>

Now let's add some styling. Nothing too fancy just yet.

.navigation {
  max-width: none;
  background: #000;
  padding: 0;

.navigation li {
  float: left;

.navigation li a {
  display: block;
  color: #fff;
  padding: 10px;

.navigation li a:hover {
  background: #0fcaf2;

Next, we'll need to add a toggle button that will trigger the menu slide on tap. Let's hide it by default. We can show it at mobile sizes later.

Right above my navigation HTML  add:

<h2 class="navheader collapse-trigger">Menu <span></span></h2>

We'll also include a span tag to display an arrow icon to the button.

Now, let's add some styles for our toggle button:

.navheader { 
  font-size: 12px;

.slide-trigger {
  display: none; /* need this */
  border: 1px solid #CCCCCC;
  cursor: pointer;
  margin-left: 15px;
  margin-right: 15px;

.slide-trigger span {
  background-image: url("/a/i/dropdown-arrows.png");
  background-position: 0 -14px;
  display: block;
  float: right;
  margin-top: 3px;
  height: 14px;
  width: 32px;

It's time for the responsive magic.

We'll need to add some styles that hide the menu, but show the trigger button at screen sizes of 560 pixels or less (you can change that number to suit your needs). We'll also want to un-float the navigation links.

@media only screen and (max-width: 560px) {
  .slide-trigger { display: block; }
    .no-js .slide-trigger { display: none; }
  .navigation { display: none; }
    .no-js .navigation { display: block; }
  .navigation { margin: 0 15px; }
  .navigation li { float: none; }
  .navigation li a { border-bottom: 1px solid #fff; }

Notice that I've added some .no-js styles. Since we'll be using jQuery to handle the sliding behavior, we want to be sure the navigation is visible, in case JavaScript is turned off (we're using modernizr to test for JavaScript).

Here's the script that we'll use to handle the sliding behavior:

(function($) {
  $.fn.collapsable = function(options) {
    // iterate and reformat each matched element
    return this.each(function() {
      // cache this:
      var obj = $(this);
      var tree ='.navigation');{
        if(':visible') ){tree.toggle();}
        if ( $(window).width() <= 570 ){tree.attr('style','');};

Now let's attach this little plug-in to our toggle button element. The script is pretty simple; it finds the next .navigation element and opens it or closes it when the toggle button is clicked. We also want to make sure the menu is visible again in case the window gets larger than 560 pixels, so let's add a little resize testing and open the navigation down at sizes of 560 pixels or more.

We can attach our plug-in to the toggle button when the document is ready:


There you have it! A working mobile toggle menu. Resize your window and watch the magic happen.

As always, feel free to tell us how you could have done this better! If you have questions, feel free to leave a comment below.

Terris Kremer's avatar

Terris Kremer

Front-end developer at Q Digital Studio

Terris Kremer is a front-end developer at Q Digital Studio. While he may joke that both front- and back-end developers are dweebs, Terris really does make development look cool. For Terris, work is a game that he can (and does) play all day long.




Code > CSS > HTML > jQuery



What others are saying


Thanks for this! It is very useful. I really appreciate it.

I found a little mistype in the line:

<h2 class=“navheader collapse-trigger”>Menu <span></span></h2>

I think ‘collapse-trigger’ should be ‘slide-trigger’.


Terris Kremer

@Martijn - Thanks reading and for finding my mistake. It’s now corrected in the article.


This is great thanks! One tiny problem I’ve come across though that you might be able to help with.

The menu stays open after resizing back through the media query on smaller viewports. So if I start with a wide viewport and make the browser window really skinny, toggle open the menu and then toggle the menu closed. Make the browser window wide again and then back down to a skinny window the menu displays as always open until I refresh and start again.

Any help much appreciated.

Terris Kremer

@Leanda - Thanks for commenting! I see what you’re after - once the menu is opened in “mobile views” is stays open when resizing between breaking points.

The reason this happens is because the JavaScript we’ve written adds an inline style of display:block to the ul.navigation element on click. This inline style supersedes our media query styles and so they won’t apply the display:none at the “less than” breaking point.

One way to get around this is to change our script so that when the window is resized larger, past our breaking point, we remove that inline style attribute instead of using slideDown.

It looks like this:

  if ( $(window).width() <= 570 ){tree.attr(‘style’,’‘);};

I’ve updated that in the demo and the article.

Thanks for pointing this out.

James Bowskill

Very useful - thanks for this. After implementing it locally I was surprised to find it not working on iPhone/iOS 5 though (neither my implementation, nor the demo page linked from here). The menu simply won’t open. Is it just me, or has anyone else found this?

Would really appreciate any help.

Terris Kremer

@James - You’re right. It turns out, unfortunately, that iOS5 doesn’t like slideDown() or slideUp(), so we’ll need to use .toggle(). We lose the slide animation, but atleast it will work this way :)

I’ve changed this in the jQuery example code so you can see what I mean.

James Bowskill

Thanks Terris. Shame the animation is lost, but better than no menu at all.

Kjetil Prestesæter

Thanks for a nice menu! One problem, though:

When I open the menu on my mobile, and scroll down to see the whole menu, it closes as soon as the H2-heading scrolls out of view. So it’s impossible to use the bottom items in a long menu. How to fix that?


Experiencing the same issue as Kjetil on some mobile devices. As soon as the screen is scrolled, the menu disappears…


Thanks for nice menu. However, my lightbox js doesn’t work at all after i use this menu. Do you know how to solve this?


Forgive my javascript illiteracy here. When you say “attach” the script to the toggle button ... what exactly do I do with this little bit of code?



This does not work with IE8 or less..
which is a pitty :-(

Any idea why?


today i’ve tried you responsive toggle menu, that’s cool and work pretty fine. But it has an inconvenient. After toggle and resize window, the old menu disapear. I find the solution line with

  if ( $(window).width() <= 570 ){tree.attr(‘style’,’‘);};

replaced with


For me it worked.


Hi Alex,

I’ve tried this but when we replace this

  if ( $(window).width() <= 570 ){tree.attr(‘style’,’‘);};



then It solved the old menu disappear problem but it makes the toggle stop woking. Any help regarding this will be highly appreciated.


I actually removed the tid-bit below entirely.

      if ( $(window).height() <= 1270 ){tree.attr(‘style’,’‘);};

Works fine for me now.  Still toggles, works on Android, and iOS.  Haven’t seen any issues.

Carlo Fardella

Just wanted to let you know that the script was failing for me when trying to integrate into a Wordpress theme and you need to change the script from:



jQuery(document).ready(function ($) {

This is due to Wordpress loading jQuery in conflicts mode. More info can be found the solution here:


Juan Pablo

I have tried using your html,css, and jquery. Do I need to attach any extra files because its not working for me. I get an error on the javascript. I use visual studio 2010.

Colleen Gratzer

Hello. I don’t know my way around javascript too well. Where do you place those last two “windows” of code above?

Jessica Seemann

thanks for this menu! but how can i use it for a drop down menu? i need a second level…?

Chris Ware

I have managed to get the menu working with a second level for those who are interested, site is


Hi I notice on the demo the ‘dropdown-arrows.png’ does not change to an ‘up’ arrow when viewing the drop down in mobile view. Can this be changed to toggle between the up & down sections of the graphic (I noticed the original png has both and just needs to shift position when dropdown is viewed). Not sure how to do this. Thanks in advance.

Hello thnks for an excellent menu its so simple an it works wonderful but i have a doubt how can i change the label “menu” for an icon i think it look a lil bit better but i note that the label its seted up in the js can i make that change?

Sorry about my english fellas but i thin make my point clear.


Hello..  Thanks for this. 

I want the menu to close when a link is pressed.  I am sure this is a simple thing, but I am just beginning to learn.


Question - where in the HTML do I add the last two bits of code (script and plug-in)?



I’m looking for a solution to the same problem that Kjetil and Damon are having with the menu vanishing once the page is scrolled. I want to have the menu stay open when scrolling the page. It works fine on desktop; however, on mobile the menu closes.


Hey Guys, how do you get the dropdown arrow to point up when the menu is in the open state? Thanks for your help..


I used it for, it s great

Lee Allan Kane

Hi thanks for this, i have been using your code for about a year now but not without its problems. It is by far, as i have searched around, the easiest of menus to implement and customizable.

Problems i have encountered are as already mentioned conflicts with various other scripts. What i did find in response to Kjetil and Damon as i was having the same problem was that if you change ‘style’ in this bit of code

  if ( $(window).width() <= 570 ){tree.attr(‘style’,’‘);};

to something else ie in my case i changed it to ‘womble’ (i know that sounds silly but i really have not much idea about script) it stops the menu from disappearing when scrolled on a android smart phone.

That’s my question, what does ‘style’ relate to?

Also i have had no luck in stopping the full browser menu from disappearing after resizing in browser.

Any how thanks very much for this it make my website look good on mobile :)


Speak your mind