Responsive Menu Tutorial

Responsive design has basically become a staple to any modern website. With this in mind, navigation must be ready to adjust to the various screen sizes possible. As you'd imagine, a 10 item long horizontal menu doesn't translate well to a cellphone' screen. However, with a bit of proper tweaking, we can make a proper responsive menu for use on mobile.

Download more of our free responsive menu templates.


Throwing in a dash of media queries isn't all that's required to make a menu responsive. You have to know what type of menu you are working with, how you want it to display, and how it behaves. Use the following check list to help guide yourself:


If your menu has a fixed amount of 3 or 4 items, you can most likely avoid needing any "special" mobile adjustments. This depends on the text though, as 4 long words would most likely cause an over flow problem.


For the most part, if you have a vertical menu, you're already set. Vertical menus are the standard format for most mobile devices, as the portrait mode lends itself to that style. In the case of a long, horizontal menu, what you'll end up doing is styling it so that at lower resolutions it basically converts into a vertical menu instead.


An important thing to keep in mind is that mobile devices don't really have a proper "hover" state. This is a desktop only concept, which needs a different approach for mobile devices. This is only a concern if your menu has submenus, as that is generally when menu's make use of the hover states to continue expanding the navigation. When thinking responsive, we need to make sure hover states can be easily convert into "taps". This means that top-level menu items can not be links and contain a submenu at the same time (unless you give them some sort of specific dropdown button to go along with them. This also means you'll want each menu item to be around at least 26-40 pixels tall, to be easy tap targets for a finger.


Usually, a long horizontal menu will want to remain as horizontal as possible until necessary. However, once you get into tablet portrait resolutions, that may become difficult. You'll have to decide whether you're okay with the menu wrapping its items, or alternatively, you can add a class to specific menu items that you don't mind simply hiding for mobile users.

Example Menu

For this tutorial, we'll keep things simple. We'll create a responsive menu, with a variable menu item count, and a 2nd level sub menu for some items:

For this menu, we'll stick to one responsive state (phone), which would make it look like this:

Menu Markup

We'll start off with some simple markup, using 4 items, with one of them containing a submenu...

<ul class="egmenu">  
  <li><a href="#">Home</a></li>
    <a href="#" class="has-sub">Products</a>
      <li><a href="#">Computers</a></li>
      <li><a href="#">Phones</a></li>
      <li><a href="#">Tablets</a></li>
      <li><a href="#">Beepers</a></li>
  <li><a href="#">About</a></li>
  <li><a href="#">Contact</a></li>

Styling with Responsive States

Once you have the markup setup, we can go ahead and add some basic styles, as well as add the submenu toggling:

ul.egmenu {  
    background: #333; 
    height: 30px;
    width: 100%; 

ul.egmenu > li {  
    float: left; 
    position: relative;  

ul.egmenu ul {  
    background: #444; 
    display: none; 
    position: absolute;
    left: 0; top: 100%;

ul.egmenu a {  
    cursor: pointer; 
    display: block; 
    color: white; 
    line-height: 30px; 
    padding: 0 10px; 

ul.egmenu li { list-style: none; }

ul.egmenu li:hover { background: #555;  }  
ul.egmenu li:hover ul { display: block;  }  

Now here's where the magic happens. For this example we want the menu to go into mobile mode if the browser window squeezes under the 480px mark. To do this, we add a media query, which then alters some of the previously defined selectors with some new properties!

@media all and (max-width: 480px) {
    ul.egmenu {  height: auto; }
    ul.egmenu > li {  float: none; width: 100%; }
    ul.egmenu a { line-height: 40px; }
    ul.egmenu ul { position: relative; }

With that block, you can probably tell, we want at 480 pixels (or less) of screen width to change a couple properties such as: making the menu height auto (instead of fixed for horizontal), take out the floats on the list items so they become vertical, make items a little taller, and put the submenu inside (instead of floating on top).

Final Touches with Javascript

Before dropping some touch-device love through Jquery, let's alter some behavior for simplicity's sake. For mobile size, we don't want to depend on the :hover state, and instead toggle it with a tap. However, notice that right now we have the last 2 :hover rule lines in our CSS, which will be applied to mobile, messing with the behavior we want. We can actually wrap this inside another media query except in reverse to the other we have!

@media all and (min-width: 481px) {
    ul.egmenu li:hover { background: #555;  }
    ul.egmenu li:hover ul { display: block;  }

Now we have a media query for everything over 480 pixels. Again, we're keeping things very simple here and are completely ignoring tablets (which can sometimes have desktop-like resolutions, but still work better with taps), but this will do for our example. At this point, if you were to try the menu on a mobile device, you would not be able to open the submenu (it would just go the whatever link you attached to the "Products" href). This is where we use some jQuery to add our toggle. Reminder: as per our considerations listed above, by using this technique we'll have to effectively kill the "Product" link. This can easily be replaced by adding an extra menu item like "All Products" or similar in the submenu itself, containing the same link, but we'll leave that one for you to figure out!

$('.has-sub').click( function(e) {

Notice how we hooked the click event (which basically translate to a tap on a touch device) to the link, rather than the parent li like we did when using :hover in CSS. This is so that we can call the .preventDefault function and avoid the link jumping to another page. However, after doing that, we do add the "tap" class to the parent li, which we now combine with this CSS:

@media all and (max-width: 480px) {
    ul.egmenu {  height: auto; }
    ul.egmenu > li {  float: none; width: 100%; }
    ul.egmenu a { line-height: 40px; }
    ul.egmenu ul { position: relative; }

    ul.egmenu li.tap { background: #555;  }
    ul.egmenu li.tap ul { display: block;  }

Notice how we added 2 lines to our mobile media query, very similar to the :hover's, but this time with the "tap" class. This will give us the same style, with our new behavior, and now with our JS will give us a touch-driven mobile menu!