It’s a sure thing that CSS3 features like transitions, animations and transforms can add extra spice to your designs.

In this article you will see how you can build an awesome CSS3 animated dropdown menu with some of these cool features.  This is something I wished to do for a while and I finally made it. I just added support for smartphones / mobile devices and fixed the navigation for iPad and iPhone also.

css3-animated-dropdown-menu-preview

Here’s a quick preview for the CSS3 animated dropdown menu that we’re going to create today:

css3-menu-animation

The HTML

The HTML structure hasn’t changed at all, simple and minimal. Here’s an excerpt:

<ul id="menu">
        <li><a href="#">Home</a></li>
        <li>
                <a href="#">Categories</a>
                <ul>
                        <li><a href="#">CSS</a></li>
                        <li><a href="#">Graphic design</a></li>
                        <li><a href="#">Development tools</a></li>
                        <li><a href="#">Web design</a></li>
                </ul>
        </li>
        <li><a href="#">Work</a></li>
        <li><a href="#">About</a></li>
        <li><a href="#">Contact</a></li>
</ul>

The CSS

I revised and improved the styles in order to create this unique CSS3 animated dropdown menu. So, below you can find the commented pieces of styles:

Mini reset

Reset the default ul styles.

#menu, #menu ul {
        margin: 0;
        padding: 0;
        list-style: none;
}

Main level

The #menu is basically the main ul for this menu. CSS3 things like gradientsshadows and rounded corners help us to create the below:

css3-menu-wrapper

#menu {
        width: 960px;
        margin: 60px auto;
        border: 1px solid #222;
        background-color: #111;
        background-image: linear-gradient(#444, #111);
        border-radius: 6px;
        box-shadow: 0 1px 1px #777;
}

Clear floats

Here is Nicolas Gallagher‘s clearing method I’ve been using lately:

#menu:before,
#menu:after {
        content: "";

        display: table;
}

#menu:after {
        clear: both;
}

#menu {
        zoom:1;
}

List elements

css3-menu-elements

Please notice the #menu li:hover > a  selector. This is perhaps the most important CSS trick for this CSS3 dropdown menu.

So, this is how this works: Select an “a” element that is child of a “li” ; the “li” element must be a descendant of the “#menu”. Read more here.

#menu li {
        float: left;
        border-right: 1px solid #222;
        box-shadow: 1px 0 0 #444;
        position: relative;
}

#menu a {
        float: left;
        padding: 12px 30px;
        color: #999;
        text-transform: uppercase;
        font: bold 12px Arial, Helvetica;
        text-decoration: none;
        text-shadow: 0 1px 0 #000;
}

#menu li:hover > a {
        color: #fafafa;
}

*html #menu li a:hover { /* IE6 only */
        color: #fafafa;
}

Submenus

With CSS3 transitons we can animate changes to CSS properties like margin or opacity. This is very cool and I’ve used this for animating the CSS3 sub-menus. The result is great if you ask me:

css3-menu-animation

#menu ul {
        margin: 20px 0 0 0;
        _margin: 0; /*IE6 only*/
        opacity: 0;
        visibility: hidden;
        position: absolute;
        top: 38px;
        left: 0;
        z-index: 1;
        background: #444;
        background: linear-gradient(#444, #111);
        box-shadow: 0 -1px 0 rgba(255,255,255,.3);
        border-radius: 3px;
        transition: all .2s ease-in-out;
}

#menu li:hover > ul {
        opacity: 1;
        visibility: visible;
        margin: 0;
}

#menu ul ul {
        top: 0;
        left: 150px;
        margin: 0 0 0 20px;
        _margin: 0; /*IE6 only*/
        box-shadow: -1px 0 0 rgba(255,255,255,.3);
}

#menu ul li {
        float: none;
        display: block;
        border: 0;
        _line-height: 0; /*IE6 only*/
        box-shadow: 0 1px 0 #111, 0 2px 0 #666;
}

#menu ul li:last-child {
        box-shadow: none;
}

#menu ul a {
        padding: 10px;
        width: 130px;
        _height: 10px; /*IE6 only*/
        display: block;
        white-space: nowrap;
        float: none;
        text-transform: none;
}

#menu ul a:hover {
        background-color: #0186ba;
        background-image: linear-gradient(#04acec, #0186ba);
}

First and last list elements styles

css3-dropdown-first-last-items

#menu ul li:first-child > a {
        border-radius: 3px 3px 0 0;
}

#menu ul li:first-child > a:after {
        content: '';
        position: absolute;
        left: 40px;
        top: -6px;
        border-left: 6px solid transparent;
        border-right: 6px solid transparent;
        border-bottom: 6px solid #444;
}

#menu ul ul li:first-child a:after {
        left: -6px;
        top: 50%;
        margin-top: -6px;
        border-left: 0;
        border-bottom: 6px solid transparent;
        border-top: 6px solid transparent;
        border-right: 6px solid #3b3b3b;
}

#menu ul li:first-child a:hover:after {
        border-bottom-color: #04acec;
}

#menu ul ul li:first-child a:hover:after {
        border-right-color: #0299d3;
        border-bottom-color: transparent;
}

#menu ul li:last-child > a {
        border-radius: 0 0 3px 3px;
}

The jQuery

As you already get used to, IE6 gets some extra attention:

$(function() {
  if ($.browser.msie && $.browser.version.substr(0,1)<7)
  {
        $('li').has('ul').mouseover(function(){
                $(this).children('ul').css('visibility','visible');
                }).mouseout(function(){
                $(this).children('ul').css('visibility','hidden');
                })
  }
});

While the :hover pseudo-class does not work for other elements than anchor, we just need to add this small jQuery snippet to fix it. It’s pretty self-explanatory.

Update: Mobile navigation support

css3-mobile-dropdown

This is something I wished to do for a while and I finally made it. I just added support for mobile devices and fixed the navigation for iPad.

You know how much I love CSS only solutions, but this time we’ll be using some jQuery to enhance this menu. To view the result, you can narrow your browser window or browse it with your smartphone.

The viewport meta tag

To maintain everything at the correct scale, the first thing added is the viewport meta tag:

<meta name="viewport" content="width=device-width, initial-scale=1.0">

Small HTML update

You need to wrap the above HTML structure using something like: <nav id="menu-wrap">. This will be our relative holder for the mobile navigation.

The jQuery add

After page loads, we’ll add the #menu-trigger element which does exactly what you think: will trigger the mobile menu when it will be clicked. Further, in the CSS, you’ll see that this element is displayed using CSS3 media queries.

Another thing here is the iPad device detection. As you can see below, we’ll remove the fancy transition effect and stick to toggling display: none/block. This way, the functionality will be maintained also on the iPad.

/* Mobile */
$('#menu-wrap').prepend('<div id="menu-trigger">Menu</div>');
$("#menu-trigger").on("click", function(){
        $("#menu").slideToggle();
});

// iPad
var isiPad = navigator.userAgent.match(/iPad/i) != null;
if (isiPad) $('#menu ul').addClass('no-transition');

The mobile CSS

Here, the CSS3 media queries do the trick. We’ll add CSS rules to override the initial styles:

#menu-trigger { /* Hide it initially */
        display: none;
}

@media screen and (max-width: 600px) {

        #menu-wrap {
                position: relative;
        }

        #menu-wrap * {
                box-sizing: border-box;
        }

        #menu-trigger {
                display: block; /* Show it now */
                height: 40px;
                line-height: 40px;
                cursor: pointer;
                padding: 0 0 0 35px;
                border: 1px solid #222;
                color: #fafafa;
                font-weight: bold;
                background-color: #111;
                /* Multiple backgrounds here, the first is base64 encoded */
                background: url(data:image/png;base64,iVBOR...) no-repeat 10px center, linear-gradient(#444, #111);
                border-radius: 6px;
                box-shadow: 0 1px 1px #777, 0 1px 0 #666 inset;
        }

        #menu {
                margin: 0; padding: 10px;
                position: absolute;
                top: 40px;
                width: 100%;
                z-index: 1;
                display: none;
                box-shadow: none;
        }

        #menu:after {
                content: '';
                position: absolute;
                left: 25px;
                top: -8px;
                border-left: 8px solid transparent;
                border-right: 8px solid transparent;
                border-bottom: 8px solid #444;
        }       

        #menu ul {
                position: static;
                visibility: visible;
                opacity: 1;
                margin: 0;
                background: none;
                box-shadow: none;
        }

        #menu ul ul {
                margin: 0 0 0 20px !important;
                box-shadow: none;
        }

        #menu li {
                position: static;
                display: block;
                float: none;
                border: 0;
                margin: 5px;
                box-shadow: none;
        }

        #menu ul li{
                margin-left: 20px;
                box-shadow: none;
        }

        #menu a{
                display: block;
                float: none;
                padding: 0;
                color: #999;
        }

        #menu a:hover{
                color: #fafafa;
        }       

        #menu ul a{
                padding: 0;
                width: auto;
        }

        #menu ul a:hover{
                background: none;
        }

        #menu ul li:first-child a:after,
        #menu ul ul li:first-child a:after {
                border: 0;
        }               

}

@media screen and (min-width: 600px) {
        #menu {
                display: block !important;
        }
}       

/* iPad */
.no-transition {
        transition: none;
        opacity: 1;
        visibility: visible;
        display: none;
}

#menu li:hover > .no-transition {
        display: block;
}

view demo

Your turn

I hope you enjoyed this article and the techniques I used. Please share your comments and questions below!

About these ads
Comments
  1. D21 says:

    hi tut! ur menu its great but when i try to copy the code that u made it seems not working with me. just wondering why it never work for me… if you have some updated codes i luv to try…

    keep it up tut!

  2. palimadra says:

    Dhiraj,

    Excellent posts. Just saw your blog and I have become a follower.

    Can you please share the plugins that you are using with the theme. How do you add code (JS and CSS) to blog posts. Meaning how do you get different posts to load different CSS and JS files?

    Thanks in advance.

  3. Seth says:

    Hey Dhiraj I love the menu, btu I can’t get the dropdown to occur. I think I messed up the javascript. Can you give some more detail on the jquery part?

  4. mohammad says:

    can it use in rtl mode?how?

  5. Mohammad says:

    hi, is there any right to left support?

  6. Hi Dhiraj, the menu is really great. I want to change the background color (blue) of submenu but cannot find out, where to do. Please, can you give me a hint?

    • Dhiraj says:

      Hey Gabriele, thanks for your comment.

      You can change this hover background color (blue) by editing these color values :
      #menu ul a:hover {
      background-color: #0186ba;
      background-image: linear-gradient(#04acec, #0186ba);
      }

  7. Mike says:

    Thanks for the GREAT post. Only thing I haven’t found what to change is the hover color of the top most menu items. I would like them to turn blue just like the sub-items

  8. Mike says:

    No more than posted that and then noticed I needed to add a background-color element under
    #menu li a:hover.
    Did I do that the right way?

  9. Hi Dhiraj,
    it’s me again ;)
    I created a HTML5 Website and use the beautiful menu. Now, putting videos on one of the pages the menu will not longer drop down there. The problem exists only in Safari (Mac 5.1.7) other Browsers (FF, Chrome, Opera) work fine. I was searching for the reason, but I can’t figure out. Can you give me a hint?
    http://www.tango-querido.de/index.html

  10. Thanks for providing good information on drop down menu.Really helpful article.I am going to use this knowledge into my new website…

    visit http://www.morphtechno.com for six months industrial training in Mobile technology

  11. $nathan (); says:

    Thank you kindly, good man!

    I noticed the debugger brings up a minor error where the syntax is concerned in the viewport meta tag:

    “Viewport argument value “device-width;” for key “width” not recognized. Content ignored. Note that ‘;’ is not a separator in viewport values. The list should be comma-separated.”

  12. Harold Stam says:

    Hi Dhiraj,

    looking awesome, just what i was looking for.

    But when I minimize the width of the browser frame in firefox 18.0 EU AND opera v11 and 12.12 the minimized menubar is not shown at your example page
    http://demo.web3designs.com/css3-dropdown-menu.htm

    However the menu is working A-okay at the really interesting and beautifull tango website of Gabriele B. http://www.tango-querido.de/index.html

    Regards

    Harold

  13. Sean says:

    I have the menu in a grid but it only seems to show two of the possible five dropdown child items is there a setting to keep it on top
    regards
    Sean

  14. I’ve been surfing online greater than three hours lately, yet I never found any fascinating article like yours. It’s lovely price enough for me.
    In my opinion, if all website owners and bloggers made just right content
    as you probably did, the web can be much more
    useful than ever before.

  15. Brad Carlile says:

    Hi, MANY thanks for the awesome menu, I’m using it with some additions. Check it out and let me know what you think.
    http://www.bradcarlile.com

    Any suggestions or hints would be greatly appreciated.

    Also is there a way to change it from using $.browser.msie which means I need to use jQuery1.8.3

    http://docs.jquery.com/Utilities/jQuery.browser

    It says to use: http://docs.jquery.com/Utilities/jQuery.support

  16. Brad Carlile says:

    I forgot to mention that on
    http://www.bradcarlile.com

    1) I made the menu go to the bottom for mobile devices (iphone size)
    2) I added images to the portfolio part of the menu

  17. Brad Carlile says:

    Hi,

    I did one more thing that had been bugging me the line for the last menu item…
    on http://www.bradcarlile.com

    I did made a class for the last li in the menu then turn off the right border

    new Code:

    #menu li {
    float: left;
    border-right: 1px solid #222;
    -moz-box-shadow: 1px 0 0 #444;
    -webkit-box-shadow: 1px 0 0 #444;
    box-shadow: 1px 0 0 #444;
    position: relative;
    }
    #menu li.lastmenu {
    border-right: none;
    -moz-box-shadow: none;
    -webkit-box-shadow: none;
    box-shadow: none;
    }

  18. Esmond Soo says:

    how to add more sub menu?Like multi level menu…

  19. wadson92 says:

    Great drop down menu. I tried it and it works for me. The only thing that is slightly failing is the jQuery script since the browser property is depracated and no longer supported in jquery 1.9.1. “$.browser.msie && $.browser.version.substr(0,1)<7" produce an error in jquery 1.9.1 but it works in 1.7.1.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s