Reputation: 299
I am trying to add dropdown transition for the menu I am working on, but it seems that I have no idea what I am doing wrong. The menu itself appears instantly, ignorning the transition effect.
CSS code I use for transition:
-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;
opacity:0;
As far as I know I should add it to the nav ul ul
CSS block, and adding opacity:1
to nav ul li:hover > ul
but it does not work.
And here's whole code of the menu.
HTML
<nav>
<ul>
<li><a href="http://www.www.com/">Menu 1</a></li>
<li><a href="http://www.www.com/">Menu 2</a></li>
<li><a>Dropdown Here</a>
<ul>
<li><a href="http://www.www.com/">Dropdown1</a></li>
<li><a href="http://www.www.com/">Dropdown2</a></li>
<li><a href="http://www.www.com/">Dropdown3</a></li>
</ul>
</li>
<li><a href="http://www.www.com/">Menu 4</a></li>
<li><a href="http://www.www.com/">Menu 5</a></li>
</ul>
</nav>
And the CSS I am using
nav ul {
background: #efefef;
background: linear-gradient(top, #efefef 0%, #bbbbbb 100%);
background: -moz-linear-gradient(top, #efefef 0%, #bbbbbb 100%);
background: -webkit-linear-gradient(top, #efefef 0%,#bbbbbb 100%);
box-shadow: 0px 0px 9px rgba(0,0,0,0.15);
padding: 0 25px;
border-radius: 10px;
list-style: none;
position: relative;
display: inline-table;
float:right;
z-index:9999;
}
nav ul ul {
display: none;
-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;
opacity:0;
}
nav ul li:hover > ul {
display: block;
opacity:1;
}
nav ul:after {
content: "";
clear: both;
display: block;
}
nav ul li {
float: left;
}
nav ul li:hover {
background: #4b545f;
background: linear-gradient(top, #4f5964 0%, #5f6975 40%);
background: -moz-linear-gradient(top, #4f5964 0%, #5f6975 40%);
background: -webkit-linear-gradient(top, #4f5964 0%,#5f6975 40%);
}
nav ul li:hover a {
color: #fff;
}
nav ul li a {
display: block;
padding: 30px 20px;
color: #757575;
text-decoration: none;
}
nav ul ul {
background: #5f6975;
border-radius: 0px;
padding: 0;
position: absolute;
top: 100%;
}
nav ul ul li {
float: none;
border-top: 1px solid #6b727c;
border-bottom: 1px solid #575f6a;
position: relative;
}
nav ul ul li a {
padding: 15px 40px;
color: #fff;
}
nav ul ul li a:hover {
background: #4b545f;
}
nav ul ul ul {
position: absolute; left: 100%; top:0;
}
Upvotes: 4
Views: 62275
Reputation: 1748
Try this 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>
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: becomes )
<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>
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 */
}
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 */
}
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;
}
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;
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;
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">
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]-->
and add this rule to the css:
/* unfortunate ie7 gap fix */
.ie7 .navigation ul ul li{
margin-bottom:-3px;
}
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;}
add the arrow class to the links that have tertiary menus: ie: Level 2 - 1
Upvotes: 1
Reputation: 5150
You're transitioning only height, so the element that needs to change on the hover is height.
transition: height 0.3s ease-in;
^^^^^^
Now the hover CSS is changing the opacity and the display properties, see:
nav ul li:hover > ul {
display: block;
opacity:1;
}
So whatever property you want to transition needs to be referenced in the transition statement. You can use "all" for quick way to grab all the changing properties:
transition: all 0.3s ease-in;
Also note that display
is not a property than can be transitioned. To hide your ul
, you can give it height
0, and then a specific height on the hover.
Upvotes: 1
Reputation: 5625
Your transition doesn't fire, because the height
of your elements isn't changed during :hover
, only display
and opacity
. To make your elements fade in - you need to change your transition property to opacity
or all
.
If you want to transition height - you need to set your element height
to 0, and then change it on :hover
.
Be aware though - height transitions work only for specified height
value, and won't work for something like height: auto;
. There is a workaround for it, as follows:
ul {
transition: all 0.5s;
max-height: 0;
}
ul:hover {
max-height: 200px; //or whatever could be your max-height value - don't overdo it, will be crappy transition.
}
Upvotes: 10