<

Animated multi-level drop-down menus without Javascript

Published on
17,448 Points
4,448 Views
5 Endorsements
Last Modified:
Awarded

Lovely Animated Drop-down Menu - without javascript


We're going to be using CSS3 transitions to make the menus slide down gently, and the background colors fade softly in and out.

This is a barebones multi-level drop down menu made entirely in CSS, that plays nice in all browsers and degrades gracefully to regular CSS2 hover effects in IE.

We're also going to address a couple of typical layout challenges in IE.

The goal of this tutorial is to provide only the most fundamental code necessary for the implementation of the drop-down menu, which can then be used as a template for styling to your heart's content.

[We will not be using the usual display:none, display:block technique, so don't look for it]

Step 1.
Let's set up our html. We're going to put our menu inside a header, and we're also going to create a "content" area below the header.

A little explanation:
This part of the process addresses IE's stacking order, and will ensure that our menu doesn't render behind the Content area, an issue I have seen often. A typical scenario is to have some kind of image scroller under the header, which requires the scroller container to have relative positioning, and causing the menu to render behind the scroller in IE. In order to fix this, our Header MUST must have position:static.

<!DOCTYPE HTML>
<html lang="en">
<head>
<meta  charset="UTF-8" />
<title>CSS3 Horizontal sliding menu</title>
<style>
.header{
	width: 600px; 
	height:50px; 
	border:1px dotted grey;
}
.content{
	position:relative; 
	width: 600px; 
	height:500px; 
	color:white; 
	background-color: #e6056f; 
	overflow:hidden;
	}
.item{
	position:absolute; 
	top:50px; 
	left:20px; 
	width: 600px; 
	height:400px; 
	background-color: grey;
	}
</style>
<body>
    <div class="header">
        <div class="navigation">
        </div>
    </div>
    
    <div class="content">
    	<div class="item">
    	</div>
    </div>

</body>
</html>

Open in new window


Step 2.
We're going to use an unordered list to create the menu structure and place it inside the navigation div:
(make sure you replace the #'s with actual links, for example: <a href="#"> becomes <a href="mypage.html">)

            
<ul>
                <li><a href="#">Main - 1</a>
                    <ul>
                        <li><a href="#">Level 2 - 1</a></li>
                        <li><a href="#">Level 2 - 2</a></li>
                        <li><a href="#">Level 2 - 3</a></li>
                        <li><a href="#">Level 2 - 4</a></li>
                    </ul>
                </li>
                <li><a href="#">Main - 2</a>
                    <ul>
                        <li>
                            <ul>
                                <li><a href="#">Level 3 - 1</a></li>
                                <li><a href="#">Level 3 - 2</a></li>
                                <li><a href="#">Level 3 - 3</a></li>
                                <li><a href="#">Level 3 - 4</a></li>
                                <li><a href="#">Level 3 - 5</a></li>
                            </ul>
                            <a href="#">Level 2 - 1</a>
                        </li>
                        <li>
                            <ul>
                                <li><a href="#">Level 3 - 1</a></li>
                                <li><a href="#">Level 3 - 2</a></li>
                                <li><a href="#">Level 3 - 3</a></li>
                                <li><a href="#">Level 3 - 4</a></li>
                                <li><a href="#">Level 3 - 5</a></li>
                            </ul>
                            <a href="#">Level 2 - 2</a></li>
                        <li>
                            <ul>
                                <li><a href="#">Level 3 - 1</a></li>
                                <li><a href="#">Level 3 - 2</a></li>
                                <li><a href="#">Level 3 - 3</a></li>
                                <li><a href="#">Level 3 - 4</a></li>
                                <li><a href="#">Level 3 - 5</a></li>
                            </ul>
                            <a href="#">Level 2 - 3</a></li>
                        <li><a href="#">Level 2 - 4</a></li>
                    </ul>
                </li>
                <li><a href="#">Main - 3</a></li>
                <li><a href="#">Main - 4</a></li>
            </ul>

Open in new window


Step 3.
To position the menu horizontally we'll use float:left on the menu items and a couple of basic styles to make it presentable:

      
.navigation {
            width:600px;
        }
        .navigation ul{
        /* positioning */
        	position:relative;
            z-index:1000;
        /* remove the dots next to list items: */
            list-style:none; 
        /* get rid of any default or inherited margins and padding: */
            margin:0; 
            padding:0; 
            
        /* styling: */
            font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
            font-weight: normal;
            font-size: 15px;
        }
        
        /* we're using the direct descendant selectors > to ONLY affect the main menu items */
        .navigation > ul > li {
        /* positioning */ 
            position: relative;
            float: left;
        /* styling: */
            margin-right: 10px;
        }
        .navigation > ul > li > a {
        /* positioning */ 
            display:block;
        /* styling: */
            background-color: #2c2c2c; /*  grey */
            padding:8px 14px;
            text-decoration:none;
            color:#aaaaaa; 
            
        }
        .navigation > ul > li > a:hover{
        /* styling: */
            background-color:#666666; /* grey */
            color:#eeeeee; /* light grey */
        }

Open in new window

       
Step 4.
The drop-down boxes. We are going to apply the same styles to secondary and tertiary drop-downs, but you can choose to add additional styles to differentiate them.

       
.navigation ul ul{
            
            background-color:#e6056f; /* remove. this is for illustration purposes only */
            width:340px; /* you need a width to accommodate tertiary menus */
            
            position:absolute;
            z-index:100;
            
            height: 0;
            overflow: hidden;
        }
        

        /* don't display tertiary box yet */
        .navigation > ul > li:hover ul ul, .navigation > ul > li > a:hover ul ul{
            height:0;
            
        }
        /* tertiary drop-down box */
        .navigation ul ul ul{
            left:170px;
            width:170px;
        }
        
        .navigation > ul > li:hover ul, .navigation > ul > li > a:hover ul,
        .navigation ul ul li:hover > ul, .navigation ul ul li a:hover > ul{
            height:220px; /* need a height to accommodate any tertiary menus */
        }
        
        /* drop-down item styles */
        /* if you want different styling for tertiary menus, just copy the 4 rules below and insert an additional ul: for example: ".navigation ul ul li", becomes: ".navigation ul ul ul li" */
        
        .navigation ul ul li{
            background-color:#eaeaea; /* grey */
            width:170px;
        }
        
        .navigation ul ul li:hover {
            background-color:#999; /* grey */
        }
        
        .navigation ul ul li a {
            display:block;
            text-decoration:none;
            margin:0 12px;
            padding:5px 0;
            color:#4c4c4c; /* grey */
        }
        .navigation ul ul li a:hover, .navigation ul ul li:hover > a {
            color:#ffffff; /* white */
        }

Open in new window

       
Step 5 - optional
I like to have separator lines between menu items, but only BETWEEN menu items. And I don't want them to go all the way to the edges of the drop-down box either, which means more CSS tweaking, but I think it looks nicer.

Normally we could use :last-child to remove the last line in the list, but since IE doesn't recognize :last-child, we'll use the + selector instead. The following rules insert lines between each menu item, and make sure we don't have any extraneous unwanted lines either. It's a little hairy to get your head around at first, but it works across the board. And since the lines don't go all the way to the edges, it also makes sure there are no weird gaps when you hover over an item.

      
.navigation ul ul ul li a{
            border:0 !important;
        }
        .navigation ul ul ul li + li a{
            border-top:1px dotted #999 !important;
        }
        .navigation ul ul li + li a{
            border-top:1px dotted #999;
        }
        .navigation ul ul li:hover + li a{
            border-top:1px solid #eaeaea;
        }
        .navigation ul ul ul li:hover + li a{
            border: 0 !important;
        }
        .navigation ul ul ul li:hover + li{
            border-top:1px solid #999 !important;
        }

Open in new window

       
Step 6.
THE MAGIC


So by now you should have a plain vanilla CSS drop-down menu. Let's add the magic.
It's actually going to be really easy.

Add these properties to the .navigation ul ul rule:

          
-webkit-transition: height 0.3s ease-in;
            -moz-transition: height 0.3s ease-in;
            -o-transition: height 0.3s ease-in;
            -ms-transition: height 0.3s ease-in;
            transition: height 0.3s ease-in;

Open in new window


And these, to the .navigation ul ul li rule:

          
-webkit-transition: background-color 0.3s ease;
            -moz-transition: background-color 0.3s ease;
            -o-transition: background-color 0.3s ease;
            -ms-transition: background-color 0.3s ease;
            transition: background-color 0.3s ease;

Open in new window

   
Step 7.
Just one more thing if you care about IE 7.

To remove the gaps between menu items in IE 7, I'm going to add some conditional statements into the top of the file:

Replace these two lines
<!DOCTYPE HTML>
<html lang="en">

Open in new window

at the top of your file with this:
<!DOCTYPE HTML>
<!--[if lt IE 7 ]> <html class="ie6" lang="en"> <![endif]-->
<!--[if IE 7 ]>    <html class="ie7" lang="en"> <![endif]-->
<!--[if IE 8 ]>    <html class="ie8" lang="en"> <![endif]-->
<!--[if (gte IE 9)|!(IE)]><!--> <html lang="en"> <!--<![endif]-->

Open in new window


and add this rule to the css:

/* unfortunate ie7 gap fix */
        .ie7 .navigation ul ul li{
            margin-bottom:-3px;
        }

Open in new window

 
That's it!

An optional enhancement:
I'm going to add a little arrow to the items that have tertiary menus:

make an arrow.png graphic, and add this rule to your css:
.arrow{background:url(arrow.png) right center no-repeat;}

Open in new window

 

add the arrow class to the links that have tertiary menus:
ie: <a href="#" class="arrow">Level 2 - 1</a>  

Also, you'll want to remove the background-color in .navigation ul ul. It was meant for illustration purposes only.

Enjoy!

The file is here for your perusal (view source):
CSS3-dropdown3.html
- or -
http://candpgeneration.com/CSS-dropdowns/CSS3-dropdown3.html
5
Enjoy this complimentary article view.

Get unlimited access to our entire library of technical procedures, guides, and tutorials written by certified industry professionals.

Get 7 days free
Click here to view the full article

Using this article for work? Experts Exchange can benefit your whole team.

Learn More
COLLABORATE WITH CERTIFIED PROFESSIONALS
Experts Exchange is a tech solutions provider where users receive personalized tech help from vetted certified professionals. These industry professionals also write and publish relevant articles on our site.
Ask questions about what you read
If you have a question about something within an article, you can receive help directly from the article author. Experts Exchange article authors are available to answer questions and further the discussion.
Learn from the best.