Grow your CSS skills. Land your dream job.

Convert a Menu to a Dropdown for Small Screens

Published by Chris Coyier

The Five Simple Steps website has a responsive design with a neat feature. When the browser window is narrow, the menu in the upper right converts from a regular row of links into a dropdown menu.

When you're on a small screen (iPhone shown here) and click the dropdown, you get an interface to select an option where each option is nice and big and easy to choose.

That sure makes it easier to pick a place to go than a tiny link. Yeah, it's two taps instead of one, but that's arguable since you'd probably have to zoom in to tap the right link otherwise.

The HTML

The HTML for these two menus is different. As far as I know, you can't style <select> and <option> elements to look and behave like <a>s or vice versa. So we need both. You could just put both in the markup. That's what Five Simple Steps does:

<nav> 

  <ul> 
    <li><a href="/" class="active">Home</a></li> 
    <li><a href="/collections/all">Books</a></li> 
    <li><a href="/blogs/five-simple-steps-blog">Blog</a></li> 
    <li><a href="/pages/about-us">About Us</a></li> 
    <li><a href="/pages/support">Support</a></li> 
  </ul> 
  
  <select> 
    <option value="" selected="selected">Select</option> 
    
    <option value="/">Home</option> 
    <option value="/collections/all">Books</option> 
    <option value="/blogs/five-simple-steps-blog">Blog</option> 
    <option value="/pages/about-us">About Us</option> 
    <option value="/pages/support">Support</option> 
  </select> 

</nav>

Let's go with that for now.

The CSS

By default we'll hide the select menu with display: none;. This is actually good for accessibility, as it will hide the redundant menu from screen readers.

nav select {
  display: none;
}

Then using media queries, we'll do the switcheroo at some specific width. You can determine that on your own (here's some standard breakpoints).

@media (max-width: 960px) {
  nav ul     { display: none; }
  nav select { display: inline-block; }
}

But now you gotta maintain two menus?

Well yeah, that's one concern. Maybe your menus are created dynamically and you can't control the output easily. Maybe you and hand crafting menus but want to make sure you don't accidentally get your menus out of sync. One way we can fight this is to dynamically create the dropdown menu from the original.

Using jQuery, we can do that with just a few lines of code:

// Create the dropdown base
$("<select />").appendTo("nav");

// Create default option "Go to..."
$("<option />", {
   "selected": "selected",
   "value"   : "",
   "text"    : "Go to..."
}).appendTo("nav select");

// Populate dropdown with menu items
$("nav a").each(function() {
 var el = $(this);
 $("<option />", {
     "value"   : el.attr("href"),
     "text"    : el.text()
 }).appendTo("nav select");
});

Then to make the dropdown menu actually work...

$("nav select").change(function() {
  window.location = $(this).find("option:selected").val();
});

But aren't dropdown menus kinda obtrusive?

Kinda. Most small screens these days are mobile and most mobile devices are JavaScript friendly, so not a huge concern. But, if you want to ensure this works with or without JavaScript I have an article about that.

Demo & Download

View Demo   Download Files

Video

Quick video example in case you are reading this from somewhere you can't adjust the browser size and play with it to see what the heck we're talking about here.

Variations

Comments

  1. This cracks me up. I’ve just spent an hour this morning googling around for the solution to this problem. You rock, sir.

  2. Bradley Rosenfeld
    Permalink to comment#

    I personally hate dropdown menus for links. But this could be useful in some situations (like the example site you found).

    Also I hate the redundancy. Having to use jQuery to fix it isn’t much better in my opinion.

  3. This is cool. A good option for large navigation menus. I don’t think I’d use it for small menus.

  4. JQuery is really redundant here. You can easily make the same through DOM and even ES5 methods. Current mobile browsers engines are modern enough, so you don’t need to worry about old and limited engines such as IE.

    • Every single thing jQuery can do is redundant, because it’s just JavaScript and could be written that way instead. I use it here because it makes the code I write and present just a few lines. But eff yeah man, rewrite that shit in in whatever you feel is best for your project.

    • Chris, you wrote ‘in’ two times (between sh*t and whatever).

    • Yes, but what if you have Windows Phone 7?

    • Adam
      Permalink to comment#

      Aaron, are you actually correcting him for typing “in” twice on a comment??? Come on man….don’t you have anything better to do?

    • Adam, I just saw a spelling error. Just wanted to let Chris know. If it sounded rude, then my apologies.

  5. Permalink to comment#

    I’ve been using display:none for a lot of things when using media queries, but it feels like I’m cheating.

    • Sean
      Permalink to comment#

      I wouldn’t worry about it, at the end of the day you need to do whats best for your users, and using display: none hides the extra navigation from screen readers so doesn’t seem to be any accessibility concerns..

      Or did you mean using display:block feels like your cheating on display: inline-block ?, i sometimes feel a bit closer to certain CSS selectors than i should

  6. The demo doesn’t seem to work on my iphone. It shows up as a menu, not a dropdown.

    • Permalink to comment#

      Same here! did not work on my iPhone 4. gonna check out the code and see what happened.

    • The demo page isn’t really a mobile friendly page. In your implementation, you would use the meta tag for making the viewport the device width and then the media query would work as expected.

  7. I like it. I never thought about using a select as a navigation element … but it does seem to make sense for mobile devices.

  8. I must say this was an interesting solution.
    Have to try it out on a site some time soon =)

  9. neat little trick i must say.

  10. Rikudo Sennin
    Permalink to comment#

    Very good, but I think that if the window is too small, the navigation should become vertical, rather then turning into a select.

    Semantically speaking, a select is used to select options in a form, in cases were free text input shouldn’t be allowed (Select your gender: [Male] [Female] etc.)

    This argument is similar to the argument of not using links as javascript subjects (href=#), but instead to use buttons as that is they purpose (having action done on the page).

    In short, <select> elements should not be used in navigation, but as a form element. That’s why the <ul> is there.

    • I kind of agree with your argument that a is not semantically correct, but I think when designing for mobile sometimes semantics can be put aside in order of functionality, because mobile is just in its child shoes and needs to grow a lot.

      And, just as a sidenote, the gender example is not correct either, radiobuttons should be used for that specific example.

    • Sean
      Permalink to comment#

      I agree with Pieter….we definitively want to be using semantically appropriate elements as much as we can, but not at the expense of the users experience, i think the trade off is worth it here

  11. wow… i like this trick.. so where is the +1 Button ?? :)

  12. Awesome trick,will implement

  13. I’d like to know how you made your site fit so many different browser sizes.

  14. I’m using this exact same method on my site! I saw it on Yaron Schoen’s website. If you want to generate a dynamic dropdown from your WordPress pages, just use this function: wp_list_pages()

  15. Chris
    Permalink to comment#

    Very neat little trick, cheers Chris!

  16. Permalink to comment#

    yes nice!

  17. Really nice i would also make a “Jump to:” text appear before it

  18. Permalink to comment#

    Genius. Once more. Thanks for sharing.

  19. This is very useful to know, especially with so many people browsing the web with mobile devices these days. Thanks again for yet another amazing article Chris!!

  20. Very useful tutorial. Thanks for sharing Chris!

  21. shridhar
    Permalink to comment#

    itz really nice… :)

  22. It’s a nice effect but the fivesimplesteps.com menu becomes a drop-down at around 767px, doesn’t that seem too big? In other words doesn’t the viewport have to be /really/ small to warrant a drop-down?

  23. Very neat trick chris… you are on of my 5 a day!

    Just a quick tip, if your like me & want to make life easier & updating quicker, you could use a PHP array or have the menu dynamic from a database, so you only have to edit/add/remove the menu data once, then use a loop for the select & the ul section:

    <?php
    
    $navArray = array(
    	'Home' => '/',
    	'Books' => '/collections/all',	
    	'Blog' => '/blogs/five-simple-steps-blog',
    	'About Us' => '/pages/about-us',
    	'Support' => '/pages/support'
    );
    
    ?>
      
    <?php 
    	  foreach ($navArray as $key => $value) {
    		  echo '' . $key . '';
    	  }  
    ?>

    Select

    <?php 
    	  foreach ($navArray as $key => $value) {
    		  echo '' .$key . '';
    	  }  
    ?>
  24. Great one Chris! Will definitely use this in my projects. Thanks!

  25. Hey Chris! Good idea and excellent realization. Thanks for sharing!

  26. Chris, this is just an great idea. Responsive web design is becoming more popular every day.

  27. Nice, but I don’t like that you either have unused tags in your HTML or have to rely on JavaScript. Each isn’t the best solution.

  28. Hi Chris.

    I hope you don’t mind. Your article got me thinking. Here’s what’s came out: http://www.itmitica.com/en/articles/css3/s-menu/

    In short, the container element for the menu links should act accordingly and provide scrollable means and a confined space to make the menu friendlier for small screens.

  29. I personally think this example is a step backwards. I mean I go to your website on my mobile device and have to take an extra step to find what I need? Really? It’s not as if the example you show has a huge navigation to start with is it? They could lose the home link (and linke the FSS logo to the index.html) allowing the navigation to fit in one line. The only way I see drop downs working is on a site with inherently huge navigation and sub navigation. The ESPN mobile site, I feel, does this well. Adding an extra step rather than rethinking your small navigation is not satisfactory.

  30. Permalink to comment#

    CSS tricks is really awesome i came here through google…and now though that i have explored css-tricks i found that it is an awesome place for all the designers out there…
    great work people…and thank you for such a useful tutorial

  31. Daniel Cuttridge
    Permalink to comment#

    @Chris Coyier

    You could easily serve markup for the dropdown menu without ever going near JavaScript.

    At least that’s the idea, I’ve got it working and I can provide a few neat examples of how you can provide markup like that with media queries…

    There are a few drawbacks but if your interested then e-mail me and I’ll send you the examples.

    • Conditionally serving markup based on screen size without JavaScript? How do you test screen size without that? Some kind of UA sniffing? Is it secret? Would love to see examples, post JS fiddles =)

  32. Hey! This solution is awesome! Thanks, like a lot of people above, I’m searching a lot in Google but no one before You don’t gave me fully solutions.

  33. Shall I have the solution for the resolution problem for my website, Because my content is getting down from the menu, if the resolution is less 1280*1024.
    Let me have the right solution for my problems.

    Awaiting with regards,
    Narendran,
    Tweet me @MyNaren89,
    9487693560.

  34. Lucas Sandoval
    Permalink to comment#

    look great, man! but, we got a problem whit html seletc element as a anchor. Is important to add a “Go” button next to it so that the user is taken only when you click. it´s for usability

  35. Nice man. Thanks for scripts.

  36. Edgar
    Permalink to comment#

    It doesnt work on an iphone because the iphone resolution is 960, the dropdown display none property deactivates when the resolution is less than 960…

  37. Really cool stuff…Thanks for sharing

  38. Permalink to comment#

    Very good i would also make a “Jump to:” text appear before it

  39. Permalink to comment#

    Thanks for the code. This worked great. I came up with a bit of an addition for you though. If your original menu has sub menus, it would be nice for that to be reflected in the select menu. Here’s an addition for this:

    For a menu with this kind of markup:

    <nav id="main-nav">
    <ul id="menu">
    <li id="item-1">
    <a href="/">Home</a>
    </li>
    <ul class="sub-menu">
    <li id="item-2">
    <a href="#">Example</a>
    </li>
    </ul>
    </ul>
    </nav>

    New JavaScript:

    // Populate dropdown with menu items
    $("nav a").each(function() {
    var el = $(this);
    var da = '';
    if($(this).parents('.sub-menu').length){
    da = '- ';
    }
    $("<option />", {
    "value" : el.attr("href"),
    "text" : da + el.text()
    }).appendTo("nav select");
    });

    • Permalink to comment#

      Thank you – works great!
      If you want more levels on menu:

           if($(this).parents('.sub-menu').length){
          da = '- ';
          }
           if($(this).parents('.sub-menu').length == 2){
          da = '- - ';
          }
      

      And so on…

    • Alexander
      Permalink to comment#

      Thank you! That was really helpful.

    • Eduard
      Permalink to comment#

      Hi.

      Is it possible to make only the parent of the levels bold?

      Thank you.

  40. Daniel Weber
    Permalink to comment#

    Hey Chris,

    Here’s a simple alternative to dropdown navigations at smaller screen sizes: Move the navigation from one of the first things to appear on the page to one of the last things to appear. Near the top of the page, place an image of a list icon that is anchored to the newly relocated navigation. A smooth page scroll is a must for this to work. That’s it.

    Here is why I like this solution:
    (1) It’s easy for a novice designer/coder to implement into a project; (2) There is more space for content to instantly be viewed; (3) Some folk (typically older in age) are unaware that the small list icon image means menu. These visitors will continue to scroll down a page to find the navigation at the bottom.

    But I’m sure this “solution” is nothing new.

  41. Jason
    Permalink to comment#

    Thanks this worked great!

  42. Venkatesh
    Permalink to comment#

    Hi, I used drop down menu in that I added a background image for clicking a menu. While in desktop on hovering image works fine. While in iPhone or iPad, on hovering background image not working properly.

  43. Luigy
    Permalink to comment#

    Hi I have used your code and I got 2 go to boxes when resize the screen. What have I done wrong? Any Suggestions?
    Thanks

  44. Tom

    This pattern is not a good solution since you create additional markup just for an alternate navigation element. I call this a hack. The best solution is to use just one navigation element and lay it out.

  45. Eduard
    Permalink to comment#

    Works fine for me, but in mobile version check icon is always showing that I am on “Go to…” page, not recognize when I am on other sections.
    Detele # from link caused this.

    Any solution for this? Thank you.

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".