Grow your CSS skills. Land your dream job.

Solution For Very Long Dropdown Menus

Published by Chris Coyier

I like to be confident with post titles, but the reality in this case is a *possible* solution for very long dropdowns. The problem with long dropdowns is that the dropdown itself can go below the "fold" of the website. That is, below the visible area of the browser window. So in order to access those menu items down below, you need to scroll your browser window. For those of us with scroll wheels of some kind on our mice (mouses?), it's not a big deal. For those without, those lower menu items are totally inaccessible, because to use the browser scrollbar means mousing off the menu (and probably having it close).

 

View Demo   Download Files

 

I first saw this idea in effect on the Media Temple account center page. They have a dropdown for "Domains" in which every single one of your domains hosted with them is listed. This can be a very long list. Media Temple had implemented a technique where as you scroll down, the menu actually moved in an accelerated fashion.

Of course, as I go to take this screenshot I find that the cool solution they had complimented isn't there anymore. Kind of makes me wonder what kind of trouble they had with it, but oh well, let's roll with it. Here an attempt at visualizing the idea:

jQuery Makes it Tick

I'm going to dump the code all in here just for quick reference. I commented it, so it should be fairly easy to follow. It's over 60 lines, but don't worry too much, it's fairly simple.

  1. Set a maximum height to the dropdowns
  2. On hover, reveal the submenu
  3. Calculate a speed multiplier based on the height of the submenu
  4. Watch for mouse movement in the menu
  5. Scroll the menu with the mouse movement, based on the multiplier
  6. On mouse out, close the menu
var maxHeight = 400;

$(function(){

    $(".dropdown > li").hover(function() {
    
         var $container = $(this),
             $list = $container.find("ul"),
             $anchor = $container.find("a"),
             height = $list.height() * 1.1,       // make sure there is enough room at the bottom
             multiplier = height / maxHeight;     // needs to move faster if list is taller
        
        // need to save height here so it can revert on mouseout            
        $container.data("origHeight", $container.height());
        
        // so it can retain it's rollover color all the while the dropdown is open
        $anchor.addClass("hover");
        
        // make sure dropdown appears directly below parent list item    
        $list
            .show()
            .css({
                paddingTop: $container.data("origHeight")
            });
        
        // don't do any animation if list shorter than max
        if (multiplier > 1) {
            $container
                .css({
                    height: maxHeight,
                    overflow: "hidden"
                })
                .mousemove(function(e) {
                    var offset = $container.offset();
                    var relativeY = ((e.pageY - offset.top) * multiplier) - ($container.data("origHeight") * multiplier);
                    if (relativeY > $container.data("origHeight")) {
                        $list.css("top", -relativeY + $container.data("origHeight"));
                    };
                });
        }
        
    }, function() {
    
        var $el = $(this);
        
        // put things back to normal
        $el
            .height($(this).data("origHeight"))
            .find("ul")
            .css({ top: 0 })
            .hide()
            .end()
            .find("a")
            .removeClass("hover");
    
    });
    
    // Add down arrow only to menu items with submenus
    $(".dropdown > li:has('ul')").each(function() {
        $(this).find("a:first").append("<img src='images/down-arrow.png' />");
    });
    
});

HTML & CSS

I hesitate to dump a bunch of HTML and CSS code in here because it just isn't very interesting. You can download the code anyway, so take a peak there. It's just a normal semantic nested unordered list and some simple very basic styling.

Testing

I tested it in everything all the way down to IE 6 and it seemed good.

 

View Demo   Download Files

 

Comments

  1. Amazing idea as usual man….thanks…my knowledge of HTML/CSS is 80% taken from this site…BRILLIANT!

  2. bha
    Permalink to comment#

    break download link…

  3. Permalink to comment#

    Nice idea. The only limit I see is with the “Really Tall Menu”. It’s very hard to visualize the whole list and know if the item you’re looking for is in that list. Also, the speed is too fast and it may be hard for people to actually click on the good link (as moving the mouse a bit makes the menu move a lot).
    Anyway, it’s just some small stuff to adjust within the context of a website.
    Great job.

    • I agree. it does scroll a bit fast. If it scrolled slower, I think the length of the “really talk menu” wouldn’t be a problem.

      But this is definitely something to keep in the archives in case you ever need it. Nice code :)

  4. Florian
    Permalink to comment#

    I would prefer a multi column submenu. That way one could see all links at once. Look at the german otto catalogue for example.

    • Bert
      Permalink to comment#

      I must agree. But the idea is nice and could be usefull for other parts of a site, like portfolio…

  5. I have found on “Really Tall Menu” that I cannot see the last fews link (I checked in the source to see how many link there were meant to be)

  6. Permalink to comment#

    This is a good idea for those clients who NEED everything in the main menu navigation.

  7. OkkE
    Permalink to comment#

    Very nice trick! Only thing I would change/add is a visual indicator that there are more items then shown.

    Not all users might move the mouse over the dropdown, and when you leave the mouse on the main items, you don’t see there are more items in the drop down then listed.

  8. tanks for this solution.

  9. Really nice!
    But i think i’ll set the speed little slower than the example, and not depending on the menu height.. can be messy for the user if differents menu run at differents speeds!

    • I know what you mean, but the speed is directly correlated to the height of the submenu. The taller it is, the faster it has to travel in order to *absolutely* get to the end of the menu before the mouse reaches the bottom.

    • Snookerman
      Permalink to comment#

      wouldn’t it be possible to make the menu scroll down only when the pointer is on the bottom half of the menu and scroll up when it’s on the top half? so the scrolling wouldn’t depend on the movement of the mouse but on the position of the pointer.

    • @Snookerman: possible is possible, but i think will require a pretty-dirt ‘patch’.

      Meybe, we can consider to add two items (bottom and header, respectively) and the scroll begin only when the pointer is upon one of them (like the arrows in the standards scroll-bars, but with an hover action)

  10. Thankfully really long dropdowns are rare, well at least I have never come across one when designing a site anyway, and if there was the possibility I would always find a way around it. Im really not a fan of drop down menus, especially for navigation purposes.. The idea behind the Domain names being shown would of been a good use of it though.

    Nice tutorial anyway, if there is ever a customer who wants a dreaded below fold drop down il be sure to look up this code! Thanks

  11. Permalink to comment#

    absolutly brilliant !!!!!
    clap clap clap

  12. Thanks for this Chris! Finally a solution to solve long dropdown menus. Just an idea, but maybe an arrow pointing downwards floating at the bottom of the dropdown to indicate to the user that there are still more items will add another fine touch to it. Just my 2 cents :-)

  13. Permalink to comment#

    I read article in GReader, went straight to demo page, wanted to go back to article, but there is no back link.

    Also as others mentioned – i can’t see all categories or if there are more of them so if i’m first time on site looking 4 something specific and i hope that this is there and there isnt i probably leave or use search instead.

  14. TeMc
    Permalink to comment#

    Looks good.

    However, if I resize my screen to a height at which the “maxHeight, 400″ get’s below the fold then I will never get to see the bottom items.

    Maybe the maxHeight can be set dynamicly based on the height of the window and the position within the window at which the dropdown starts.

    For the rest, it looks and works nice. But personally I think it’s best to have a multi column generated which maximally is as wide as the horizontal menu.

    If the there is then still not enough room there could be a scrollbar (.dropdown {overflow-y: scroll} I mean).

    But back to the solution in this article, how about a scrollbar in there ? I think just having it there (although it would scroll automaticly) would be very important information for people so they ‘know’ that there is more.

    It doesn’t have to be a ‘real’ scrollbar. Just a rectangle box that moves with you might do the visual trick for those visitors that don’t move their mouse around that much (like OkkE addresses above me).


    My 2c,
    TeMc

  15. Haha, that’s a neat little trick. I try to avoid long dropdowns to begin with, but if needed, this could come in handy. Thanks!

  16. I’d like to see this effect built into a sidebar. Forget the drop-down menu. Take that 1st drop-down list, keep it expanded, and put your activity stream or blogroll in it. It might be a bit confusing the first time someone mouses over it, but they’ll “get” how it works very quickly.

    Another thought… if you’re going to use this technique as it’s done in the demo, it feels like there needs to be some sort of visual cue for how the long list of links is sorted: alphabetical or chronological (which would need dates attached.) Then it becomes much more useful… kind of like scrolling through the address book on the iPhone. Actually, an alphabetized company directory in a drop-down menu would be the perfect use for this.

    • Josh
      Permalink to comment#

      Leif, I love your idea of building it into a sidebar. Actually, I already tried to do it at this page. If you hover over ‘projects’ the list of thumbnails shows up.

      I just can’t seem to ‘Take that 1st drop-down list, keep it expanded’ as you said it. Have you found a way to do this? Thanks in advance.

    • Hey Josh,

      Nice job so far on that demo page. It’s starting to look good.

      I haven’t got around to trying to use this technique yet, but I’ve got a project that scheduled to launch by the 1st of Dec. so I’ll let you know how it goes.

      How are you doing that animated favicon, btw?

    • Permalink to comment#

      http://www.htmlkit.com/services/favicon/ this site let’s you make an animated favicon. But I think it’s only viewable in FF, at least not in Safari; then it switches back to the static one.

      I’m kinda in a hurry with this long dropdown menu thing. Can’t I just do it ‘ugly’ and replace the .hover statement in the .js with something so that it drops down immediately?

      Thanks.

  17. Carlos
    Permalink to comment#

    That is fun but I like how some people have just been making really long navigation split into columns. Similar to this White House site or REI site is.It is cool but I am not sure if people are ready for it. Usability would suffer a bit if someone was looking for something and couldn’t find it fast just by scrolling over the main nav item.

  18. You pulled that off very nicely Chris!

  19. But at least it submenu items should be accessible without javascript

  20. Zach
    Permalink to comment#

    Pretty slick, Chris. Menus like that are rare, but it’s always nice to have that technique in your arsenal.

  21. Permalink to comment#

    Wow, brilliant solution.

    I would add an indicator that moved along the y-axis on the right edge of the dropdown so the user knows their position within menu. This could also alleviate a bit of the “moves too fast” feeling some folks are getting, because any kind of uncertainty adds to that kind of thing.

  22. Great Tut! Really Useful !

  23. Permalink to comment#

    Nice, I can see how this could be useful in many areas.

  24. I really like the concept, but why not use one of the methods that are currently standard (like mega drop-down menus) rather than create something new?

    http://www.useit.com/alertbox/mega-dropdown-menus.html

    This is a really interesting proof-of-concept that you’ve created here, but I just worry in this scenario about asking too much of your users.

  25. Any particular reason you declared maxHeight outside the ondomready function? Also, why the $ on some of your variables at the top?

    var $container
    var $list
    var $anchor
    var height
    var multiplier

    Is that your way of separating out dom elements? Just a personal coding style?

    • maxHeight is outside just so it kinda stands out and is obvious. It never needs to change really.

      The $ variables are just as you suspect, they represent page elements, so that’s just an easy way to make a visual distinction.

  26. Permalink to comment#

    Brilliant!
    hemm..i think this idea could also be applied with really long sidebar menus — i’m thinking scrolling-on-mouse-hover sidebar menus lol

  27. Nice new technique, worth exploring….

  28. Permalink to comment#

    Brilliant idea. This is one of the few sites which actually comes up with good original ideas.

  29. Ah! I love it! Nice one Chris. I like how the user doesn’t have to touch anything to scroll.

  30. Permalink to comment#

    Simply awesome.

    If there is something missing, it is a pointer that showing there is more at the bottom/top so a user won’t think “the items I see are all of them”.

    But still, awesome.

  31. silvers
    Permalink to comment#

    great menu man. i know that you’e not loving “good job” but i had to show my appreciation!

    i haven’t seen a menu bar like this before and i have been wanting to implement a drop down in to a website cos clients seem to like them. I might try and put this in a wordpress site when i am feeling confident too.

    seriously man, just like someone else said “my knowledge of HTML/CSS is 80% taken from this site…BRILLIANT!”

  32. Permalink to comment#

    Chris; Cool idea! When I browsed the HTML I noticed that you have the arrow as an tag inside the anchor. Why aren’t you setting the arrow as an background to the anchor? I would argue that the arrow is a presentational image! Just a thought!
    Thanks!

  33. Permalink to comment#

    wow ! I’ll use this on next site

  34. Pawan
    Permalink to comment#

    Cool !
    When you reach to the bottom of Realy Tall menu, the user just falls below the dropdown and the dropdown closes. So, if the user does not know the last element in the dropdwon, he will always fall from the dorpdown. It may be better to keep displaying the last few items, and only vanish the dropdown when the user’s mouse is taken out of the menu.

    I know I could not explain this in a good manner, still I hope this much can help.

  35. Permalink to comment#

    Man, Chris! You never cease to amaze me with the solutions you come up with!

  36. Permalink to comment#

    Great fix Chris!
    I wonder if MediaTemple will use this for their dropdowns after seeing it?
    A visual cue for the drop down would be nice (like an arrow to show at the bottom and when it’s done hide it (while showing the top arrow) so users know this has more. I didn’t know how it was by just viewing the demo until I hovered inside the drop down menu items.

  37. Permalink to comment#

    i love your articles about better css coding, plz more of them. the menu is great :-)

  38. Permalink to comment#

    Nice work… no substitute for effective navigation planning but definitely worth a bookmark!

  39. Permalink to comment#

    Am I the only one who finds this menu unusable? If you come from the top and want to click on the third link, the menu will automatically scroll down and the link you wanted to click will not be visible anymore.

    I’m afraid the audience here is a little biased since we’re all web designers. “Normal” people would probably hate a menu like this.

    • Permalink to comment#

      It’s not unusable, it just takes a few seconds to realise how it works.

      But yes we are biased :)

    • Permalink to comment#

      it’s “cool” but I agre it’s unusable… and totally not accessible. If you need this kind of menu you certainly have an error in your website architecture. Any way dropdown are bad design in 99,99% of time.

      This one is specially bad:
      – don’t expose all options
      – need understand a new UI widget
      – demande a great amount of manual dexterity (not accessible for all peoples)

      Good for:
      – realy i don’t know but yeah.. it’s fun so use it for portfolio because -> http://twitter.com/gagarine/status/5097314179

    • Hey, its just an idea.
      Agree with you that can be confusing, but with a small edit it will works great (for example, instead of scrolling automatically, adding two arrows both at the top and at the bottom and only scoll when the mouse over the arrows).

      For the accessibility, the xhtml markup its just a unordered list, nothing more accessible.

  40. Permalink to comment#

    Very neat idea. Would it be possible to get an updated version that supports navigating with the keyboard, for accessibility purposes?

  41. Permalink to comment#

    Sweet! :D

  42. Permalink to comment#

    Interesting solution. Personally, I think a more appropriate solution would be to eliminate the long dropdown altogether, and perhaps re-examine the information architecture of your site.

    Of course, that’s not always possible, especially if your client has the ability to add pages with a CMS. In those situations this might work OK.

    One suggestion I have would be to add a class to <a> tags which contain submenus, rather than inserting an <img> tag.

    Something along these lines:

    $(".dropdown > li:has('ul')").addClass('submenu');

    This allows you to add arrow icons with CSS, rather than inserting presentational markup with JavaScript.

  43. Awesome Idea and I love the scrolling effect. But one very tiny winy drawback I think is that what if the user doesn’t hover the mouse over any of the list items? He won’t be able to know that anything exists other than the items being displayed. May be it can be notified somehow that there are more items to be scrolled?

  44. Hi,

    I’m currently trying to make the menu vertical. I got it vertical and i got it to display the submenu on the right, but it works only if it hasnt the scroll effect in it. If it has the scroll effect it will dissapear like behind the background. I tried overflow: visible, but its not the solution :P

    How do I get rid of that little problem?

    The menu is freaking awesome btw :D

  45. YUI has a menu that automatically adds a scroll up and a scroll down button when the menu is too long. That seems to work pretty well.

  46. Dave Calleja
    Permalink to comment#

    This is fucking amazing. Such an elegant solution.

  47. chris p
    Permalink to comment#

    this is tending towards the nice scroll selector in the iphone.
    some suggestions:
    – change the font size of the items at the edges for visual cue
    – automatically add a non-selectable last item of 3 dots, as a cue to end of list

    some information is better presented differently, but there is legit cases for a long list selector

    good work
    cheerd

  48. Permalink to comment#

    nice menu

  49. Permalink to comment#

    Here is a little addition to calculate the maxHeight (so it doesn’t go bellow the window height in any case)

    var maxHeight = $(window).height() – ($(‘.dropdown’).offset().top + $(‘.dropdown’).outerHeight());

    Notice: I haven’t tested it, but should work without a problem…

  50. jammer
    Permalink to comment#

    How can I avoid the content below the long drop down don’t move down. Because every time it hover the content below also moves so its destruct the content.

    Any help?

  51. Pretty cool idea. As some others already have mentioned, it needs some kind of indicator that shows how far down the list you are. This could be a pretty cool feature for a lot more than a typical dropdown menu. Thanks for sharing the idea.

  52. Permalink to comment#

    Thanks for the great menu!

    Is there a way to make the submenus appear on top of the navigation, instead bellow it ?

  53. Permalink to comment#

    Thank you very much for this unique type of navigation. For all the negative folks; please go somewhere else.

    Now I have a question: I used your script on this page. But I want the items to already be there, not just when you go over ‘projects’. Can someone help me out to accomplish this?

    Thanks very much again.

  54. Permalink to comment#

    I tried to register on your forums, but the anti-spam confirmation cod thingy is really NOT ledgible. I couldn’t read it and after a couple refreshes, my IP got blocked and I ‘should try later’.

    I really hope someone can help me with my problem above.

  55. Permalink to comment#

    thanks good dropdown menü

  56. Sonny
    Permalink to comment#

    I absolutely love this solution for long dropdowns. I wasn’t sure if anyone else has tried to use a transparent PNG or just text without a background on the main menu item. The subnav hides behind the text and doesnt disappear before it. Check out this example…

    http://www.sonnykotler.com/nav.html

    Any Ideas?

  57. Christian
    Permalink to comment#

    Thank you for the solution. But my Debugger says ” object is required” failed :(

  58. Very nice!
    Thanks for sharing.
    :-)
    Been playing a bit with this idea here …
    http://funcityfinder.com/events/indianapolis/
    … but the “overflow:hidden” property seems to not work.
    :-(
    Any thoughts?

    Thanks Again!

  59. Jasper
    Permalink to comment#

    Thanks a lot for this great idea! Cheers!!

  60. Kicha

    Yes Good, but whts the solution for multi level submenus

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".