Identify Design
100% Giraffe Approved

Searching for all articles in the menu category...

Giraffe
Avatar of Woody

by Woody

Create a Pure CSS3 Animated Dropdown Menu

Tuesday May 15th, 2012 in CSS Tutorials

In our tutorial on Sunday we took a beginner's look at CSS transitions and some animated effects we could achieve with them. We didn't look too much at practical examples though, so in this tutorial we're going to look at how we can use the transition property to create a beautiful and animated drop down menu using pure CSS3.

The best part about using transitions on menus is the menu will retain complete functionality in browsers that do not support the transition property. Normally when we use fancy CSS3 that isn't widely supported we have to take time to ensure it degrades well so that users who use old browsers still have the core functionality of our page. If a user doesn't have transition support built into their browser they will still have the functionality of any effects that are applied just without the animation. This means if we build a fancy animated menu using just CSS3 and the transition property we can focus on making it beautiful rather than interchangeable because if the user doesn't support transitions they'll still have a menu!

With this in mind let's start making our sparkly animated menu. We're going to create a typical drop down menu using the :hover selector. When the user hovers over one of the parent links a drop down box will appear. You are welcome to change any properties to suit the page you're going to be using the menu on to save you a little time.

<div id="example1">

<div class="parent"><a href="#" class="button">Menu One</a>
<div class="sub" id="one">
<a href="/page/">A Link</a>
<a href="/page/">Another Link</a>
<a href="/page/">A Third Link</a>
</div>
</div>

<div class="parent"><a href="#" class="button">Menu Two</a>
<div class="sub" id="two">
<a href="#">More Links</a>
<a href="#">Yet Another Link</a>
<a href="#">A Final Link</a>
</div>
</div>

<div class="parent"><a href="#" class="button">Images Too!</a>
<div class="sub" id="three">
<img src="http://images.identifydesign.net/bird_in_snow.jpg" alt="Bird in Snow">
</div>
</div>

</div>

You will notice in the structure above that I have placed a separate link inside the menus. These links will be the clickable functional links of the parent wrappers. In HTML5 putting links within links causes big problems. The second links won't become visible since they belong within another link and it will also invalidate your source. Bear this in mind when constructing your menu. To fix this problem we'll simply absolutely position this link above the wrapper. Because it's inside the wrapper in the source hovering over the link will still produce the hover effects.

We'll need to add some CSS to the above. We're going to make the links appear when the user hovers over their corresponding parent link and then apply some transitions to make it flashy! You can change all the values below to suit the needs of whatever page

<style type="text/css">

#example1{

width:600px;
height:50px;
background:#000;

}

.parent{

position:relative;
display:block;
width:200px;
height:50px;
float:left;

}

.buttons{

float:left;
display:block;
text-align:center;
width:200px;
height:50px;
line-height:50px;
background:#e5e5e5;

}

.sub{

visibility:hidden; /* This hides the menu until we hover */
position:absolute;
top:50px;
left:0;
width:200px;
height:150px;
border-bottom-left-radius:10px;
border-bottom-right-radius:10px;
overflow:hidden;

}

.parent:hover .sub{

visibility:visible; /* This makes the menu visible when user hovers */
text-align:center;

}

.sub a{

color:#000;
background:#ffc34c;
display:block;
width:200px;
height:50px;
text-align:center;
line-height:50px;

}

.sub a:hover{

background:#f06000;
color:#fff;

}

</style>

So our mark-up combined with the above stylesheets produces the following simple drop down menu:

This menu is now functional, but we haven't added any animations yet. This is the fun part because it's time to be creative. How would you like your menu to behave? Do you want it to float in from different directions? Change colour? Change opacity? We're going to add three effects to our example menu. On the first link we're going to add an opacity effect, on the second a drop down effect and on the third a zoom effect - and of course we'll show you how to do it.

If you're unfamiliar with the transition property now would be a good time to familiarise yourself with it. Our tutorial: Welcome to CSS3 Transitions is a detailed look into transitions and how they work and our CSS3 Glossary: Transition entry has more information and examples. It's important you understand how transitions work because this tutorial won't be explaining that; we'll just be using them.

Make the Links Fade In

You have probably seen a fade effect somewhere on a menu before. Chances are it was made with either jQuery or Flash. The same results can be achieved using just CSS3 thanks to transition. All of the effects on this page will be made with just CSS3. As the classes are placed inside the stylesheet that loads on every page and is probably cached, you're saving on HTTP requests already from not needing to include additional scripts or files. You're also reaching a broader audience because CSS can't be blocked, like jQuery sometimes can by plugins. There's also some users who disable Javascript; CSS gets around this too.

We will declare the stylesheet for #one and add an opacity transition to it. To do this we set the original opacity to 0, the opacity when the user hovers over the parent to 1 and then add an opacity transition to the original class. We are going to make the transition smooth by adding the ease-in-out timing function. This makes the transition start slowly and finish slowly.

In order for this transition to work we'll need to replace the original visibility declaration else the hover off animation will not display. The menu will not be visible anyway because we're lowering it's opacity to zero.

#one{

visibility:visible!important;
opacity:0;
transition:opacity 0.4s ease-in-out;
-moz-transition:opacity 0.4s ease-in-out;
-webkit-transition:opacity 0.4s ease-in-out;
-o-transition:opacity 0.4s ease-in-out;

}

.parent:hover #one{

opacity:1;

}

Now we are going to...

Make the Links Slide In

There's two ways of doing this and it depends entirely on the setup of your page how you go about it. Since we can't hide overflow because the drop down menus wouldn't appear, we have to be mindful of how this is achieved. In the event your menu is being placed directly at the top of an element that you could hide the overflow on, or it's appearing on one of the borders of the page then you can slide the menu in using a left, top, and so forth, transition.

However if like our example boxes the effect is in the middle of content with no visible overflow nearby this won't work because the menu will appear and slide from above, to the left of, so forth, of the original links. This won't do! Want an example? Of course you do.

... Not so great, huh?

The solution is to use height to our advantage. If we set the original height of this box to zero and then change it with a transition it will give the effect of the box sliding from the top and without the overflow issue. This is the method we are going to use because it saves lots of time writing additional mark-up and it still looks nifty.

#two{

visibility:visible!important;
height:0;
transition:height 0.4s ease-in-out;
-moz-transition:height 0.4s ease-in-out;
-webkit-transition:height 0.4s ease-in-out;
-o-transition:height 0.4s ease-in-out;

}

.parent:hover #two{

height:150px;

}

Notice we've replaced the visibility for this menu. Most of the time you won't need to do this but it just happens in these two examples you do! It's a good habit to be in of hiding the content until it's called as it makes sure you don't get any ugly failures in the event something goes wrong.

And for our image we're going to...

Make the Menu Zoom

If you have an image you'd like to place in a frequently accessed part of your page, like an affiliation or advertising image, then placing it in the menu is a good way to go. The problem is it might be out of place without applying some styles to it. This is where our drop down menu comes in useful. The image will be hidden until the user actively hovers over its parent link, which they'll do because the text caught their interest.

But adding a snazzy effect to that image can't hurt, right? Of course not!

We're going to add a transition to the third and final menu box that will make the image zoom into focus sharply and crisply. To do this we'll need to add four transitions: height, width, top and left. We'll also need to do some basic maths for the best effect.

In our example the image is 100 x 100 pixels. The container around it is 200 x 150. This means we have to adjust the position when the third menu is hovered over to create a smooth and crisp zoom effect. We'll set the image to 300x300 and when the user hovers its parent we'll restore it to its original size. Our original wrapper is 150 high, which means we'll need to position the image half of the wrapper minus our zoomed high to the top: in this case, 300-150/2 = 75 pixels.

Repeat the maths with the left which will be 300-200/2 = 50 pixels. So position the top at -75 pixels and the left at -50 pixels:

#three img{

position:absolute;
width:300px;
height:300px;
left:-50px;
top:-75px;
transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;
-moz-transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;
-webkit-transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;
-o-transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;

}

.parent:hover #three img{

width:100px;
height:100px;
left:0;
top:0;

}

Pretty cool, huh? And there you have an animated menu using nothing but CSS3! The limitations are simply your imagination. You can create some really imaginative effects combining transition. In our last example below we're going to take advantage of transition-delay to create some timed drop down effects.

Adding Timing

You can create delays using transition-delay that will add pauses, breaks or times to transition effects and produce even better animations. Let's use our second example from above as our subject in this example. What if we wanted to make the links appear only once the drop down box had fully appeared? This is relatively simple to do. We'll use our original transition values from the second drop down menu but also add a transition on the links! That's right - transitions can be used inside transition effects. You can see where this is going... Throw in some transition-delay and you'll get staggered animations like this one. Notice I've added a line to change the background of the wrapper to the background of the links. Otherwise we wouldn't see the wrapper expand!

#two{

background:#ffc34c;
visibility:visible!important;
height:0;
transition:height 0.4s ease-in-out;
-moz-transition:height 0.4s ease-in-out;
-webkit-transition:height 0.4s ease-in-out;
-o-transition:height 0.4s ease-in-out;

}

.parent:hover #two{

height:150px;

}

#two a{

opacity:0;
transition:opacity 0.4s ease-in-out;
-moz-transition:opacity 0.4s ease-in-out;
-webkit-transition:opacity 0.4s ease-in-out;
-o-transition:opacity 0.4s ease-in-out;
transition-delay:0.4s;
-moz-transition-delay:0.4s;
-webkit-transition-delay:0.4s;
-o-transition-delay:0.4s;

}

.parent:hover #two a{

opacity:1;

}

So you can combine these delays with a plethora of properties to create some stunning menus. That's the end of our tutorial and examples though I'm afraid. Hopefully this tutorial has given you an insight into how you can combine various transition effects with interfaces to make smooth and animated menus - all with pure CSS3. If you have a page you've made that you'd like us to link to that demonstrates excellent use of transitions in a menu please leave the link in the comments below for everyone to see!

Here's a copy of the combined source with all transitions:

<style type="text/css">

#example1{

width:600px;
height:50px;
background:#000;

}

.parent{

position:relative;
display:block;
width:200px;
height:50px;
float:left;

}

.buttons{

float:left;
display:block;
text-align:center;
width:200px;
height:50px;
line-height:50px;
background:#e5e5e5;

}

.sub{

visibility:hidden; /* This hides the menu until we hover */
position:absolute;
top:50px;
left:0;
width:200px;
height:150px;
border-bottom-left-radius:10px;
border-bottom-right-radius:10px;
overflow:hidden;

}

.parent:hover .sub{

visibility:visible; /* This makes the menu visible when user hovers */
text-align:center;

}

.sub a{

color:#000;
background:#ffc34c;
display:block;
width:200px;
height:50px;
text-align:center;
line-height:50px;

}

.sub a:hover{

background:#f06000;
color:#fff;

}

/* Drop Down One: Opacity */

#one{

visibility:visible!important;
opacity:0;
transition:opacity 0.4s ease-in-out;
-moz-transition:opacity 0.4s ease-in-out;
-webkit-transition:opacity 0.4s ease-in-out;
-o-transition:opacity 0.4s ease-in-out;

}

.parent:hover #one{

opacity:1;

}

/* Drop Down Two: Slider */

#two{

visibility:visible!important;
height:0;
transition:height 0.4s ease-in-out;
-moz-transition:height 0.4s ease-in-out;
-webkit-transition:height 0.4s ease-in-out;
-o-transition:height 0.4s ease-in-out;

}

.parent:hover #two{

height:150px;

}

/* Drop Down Three: Zoom */

#three img{

position:absolute;
width:300px;
height:300px;
left:-50px;
top:-75px;
transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;
-moz-transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;
-webkit-transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;
-o-transition:height 0.2s,width 0.2s,left 0.2s,top 0.2s ease-in-out;

}

.parent:hover #three img{

width:100px;
height:100px;
left:0;
top:0;

}

/* Drop Down Two: Slider with Delay */

/* Uncomment this block to add the delay on the links

#two{

background:#ffc34c;
visibility:visible!important;
height:0;
transition:height 0.4s ease-in-out;
-moz-transition:height 0.4s ease-in-out;
-webkit-transition:height 0.4s ease-in-out;
-o-transition:height 0.4s ease-in-out;

}

.parent:hover #two{

height:150px;

}

#two a{

opacity:0;
transition:opacity 0.4s ease-in-out;
-moz-transition:opacity 0.4s ease-in-out;
-webkit-transition:opacity 0.4s ease-in-out;
-o-transition:opacity 0.4s ease-in-out;
transition-delay:0.4s;
-moz-transition-delay:0.4s;
-webkit-transition-delay:0.4s;
-o-transition-delay:0.4s;

}

.parent:hover #two a{

opacity:1;

}

Remove this and the opening comment to add the delay!*/

</style>

<div id="example1">

<div class="parent"><a href="#" class="button">Menu One</a>
<div class="sub" id="one">
<a href="/page/">A Link</a>
<a href="/page/">Another Link</a>
<a href="/page/">A Third Link</a>
</div>
</div>

<div class="parent"><a href="#" class="button">Menu Two</a>
<div class="sub" id="two">
<a href="#">More Links</a>
<a href="#">Yet Another Link</a>
<a href="#">A Final Link</a>
</div>
</div>

<div class="parent"><a href="#" class="button">Images Too!</a>
<div class="sub" id="three">
<img src="http://images.identifydesign.net/bird_in_snow.jpg" alt="Bird in Snow">
</div>
</div>

</div>

Avatar of Woody

by Woody

Archive: Dynamic, Section Specific Tabbed Navigation

Wednesday May 20th, 2009 in PHP Tutorials

Attention

This post is an archived post. This means it is old or has been archived for rewriting in the near future. Please be aware that the contents of this article or page may be out of date. If you need assistance be sure to leave comments and our community can help you.
If you've browsed around some blogs or portfolio sites lately you've probably noticed interactive tabbed navigation with links that change colour and backgrounds depending on which section of the site we're browsing. In this tutorial we're going to expand on our previous tutorial; Simple Hover Over Navigation Bars.
Interactive tabs that change colours, backgrounds and style when you hover over them are a nifty feature to any site's navigation. What's even niftier is when the state of these links is controlled by the page the user is browsing. This extra level of interactivity really helps the user feel like they're having a control over the style of your pages.

For an example of what we're going to be doing is in Identify Design's very own header. If you click on a link in the header, the link stays black and highlighted when browsing around that section.

To start off, we need the links with which to work with. From our previous tutorial we have four horizontal links ready to work with. You don't need to use our links, though. You can obviously substitute this tutorial into your own page.

For anyone who is following with our code, here it is:

<style type="text/css">

#links-wrapper a {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #000;

color: #fff;

}

#links-wrapper a:hover {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #fff;

color: #000;

}

</style>

<div id="wrapper">

<div id="links-wrapper">

<a href="/">Hyperlink One</a>

<a href="/">Hyperlink Two</a>

<a href="/">Hyperlink Three</a>

<a href="/">Hyperlink Four</a>

</div>

</div>

Adding Markets to the Links

We first of all want to setup the links so their class will change depending on which sections we're browsing. We're going to change the class of our links with variables; a variable for each section that will be used to control the formatting of individual section links.

In our example, we have four links. We're going to give them names now; Home, News, About, Links. First of all we're going to tell the Home link to show a grey background in the event the user is browsing the homepage.

Before we do this, though, we need to define the variables. In order to stop the variables being defined the URL, we're going to check to see if they're set using the isset(); function. This function checks to see if a variable is set and if not, set them ourselves to stop other people doing so.

Since we're going to be defining our variables on our pages, though, we want to see if they're not set. We use an exclamation mark to ask whether something isn't set or not.

Exclamation marks are used in PHP as a sign of checking the opposite of a function. For example, using an exclamation mark with isset(); will ask PHP to see if the variable hasn't been set. Using it with an equals if will ask if it doesn't equal something; such as if($variable != 0); will return TRUE if $variable doesn't equal zero.
We want a variable for every section. So, above our stylesheet, we want to add the following code:
<php

if(!isset($link_home)) {$link_home=0;}

if(!isset($link_news)) {$link_news=0;}

if(!isset($link_about)) {$link_about=0;}

if(!isset($link_links)) {$link_links=0;}

?>

We've now defined our variables if they've not already been defined.
Important!
Web parsers will use the last defined variable when a variable is defined multiple times, in ascending order. This means the latest definition of a variable will be used as its value. It's important to make sure any page-specific variables (such as the ones we'll be using) are defined before you include your configuration, functions or header file.
Asking whether they're set will not interfere with any variables we've defined on our pages, but will set the variables if they haven't been already to stop other people doing it. If we don't set them, somebody could visit our address and add the ?link_home= on the end and input anything they like into our source.
Very Important!
Always define variables. Any undefined variables can be manipulated in the address of your pages in the event a viewer figures out or learns which variable names you're using.
With the variables defined, we can later modify them on a page-by-page basis without risking somebody entering them in the URL and trying to inject something onto our site (For more security tips visit our Site Security Tutorials section).

Now we want to add the code to our links to make them dynamically change classes when we browse one of the above sections. To do this, we use a simple IF command. We're going to tell our code to check whether our variable is bigger than zero. If it is, we'll display a different class than normal.

We do this with the following code:

if($link_home > 0){

echo "link-highlight";

} else {

echo "link";

}

What this is doing is checking whether the $link_home variable is set to a number higher than zero. If it is, we're going to display the link-highlight link class to make this link display as our highlighted class. If it's not set above zero, we'll display the default link class instead. We want to place this code in where our stylesheet class would go, like so:
<a href="/" class="< ?

if($link_home > 0){

echo "link-highlight";

} else {

echo "link";

} ?>">Home</a>

<a href="/">News</a>

<a href="/">About</a>

<a href="/">Links</a>

Repeat this process for all four links, replacing $link_home with the other three variables where applicable. Our code should now look like this, with all four links's classes being dynamically defined:
<a href="/" class="< ?

if($link_home > 0){

echo "link-highlight";

} else {

echo "link";

} ?>">Home</a>

<a href="/" class="< ?

if($link_news > 0){

echo "link-highlight";

} else {

echo "link";

} ?>">News</a>

<a href="/" class="< ?

if($link_about > 0){

echo "link-highlight";

} else {

echo "link";

} ?>">About</a>

<a href="/" class="< ?

if($link_home > 0){

echo "link-links";

} else {

echo "link";

} ?>">Links</a>

Before we add the dynamic code that'll define our links's classes to our pages, we have to define them in the stylesheet first! We showed you define stylesheet classes in the previous tutorial. We're going to set link to the same values as we did every link and set link-highlight to a grey background and white text.

This is easily done:

<style type="text/css">

.link {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #000;

color: #fff;

}

.link:hover {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #fff;

color: #000;

}

.link-highlight {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #434343;

color: #fff;

}

.link-highlight:hover {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #222;

color: #fff;

}

</style>

Notice how we removed the link formatting on links-wrapper. Since we're defining the links with specific classes, we want to both ensure we're not defining any formatting unintentionally and also use as little space as possible. Unnecessary CSS will increase load times!
With our classes defined, it's time to refresh the page. Nothing should happen. "Huh?" you might ask; well, nothing should happen yet. We haven't defined any of the variables yet, neither have we actually changed anything except how the links are getting their formatting. They're still being formatted the same, only now instead of formatting their parent, we're formatting each link.

So now it's time to define which links are highlighted as an active section depending on what pages we browse.

Setting Variables Depending on Page

Let's assume your pages are called "index.php", "news.php", "about.php", "links.php". We need to add a small snippet of code to each of these pages that will tell our code when to classify a link as used. In order for this to work, though, you need to have the stylesheet and our pre-defined variables in a header file being included on each of these pages. Including is simple and allows easier editing of pages. If you haven't already, be sure to read up on how to dynamically include pages.

Just in case, here's the include command we're using to include our header file, "header.php", that's in the main directoy of our server.

<php

include("header.php");

?>

Inside the header file should be your stylesheet, your links and the variables we're defining. Now we're going to edit index.php and tell it we're browsing our index variable. To do this, we simply set the variable above our include. Since we defined our if statement as BIGGER THAN ZERO, we can use any number to display our home link as active.
<php

$link_home = 1;

include("header.php");

?>

With this variable defined, our "Home" link in the browser will now be using the link-highlight class and stand out from the rest! Repeat the above process with every page, replacing home with our earlier variables. Now, depending on which section of your site your users browse, the navigational tabs will change backgrounds to indicate the active link!
Remember...
You must set the variable before you include the header file with the links in. Otherwise the links will not dynamically display because they're being parsed before we set our variables to bigger than zero. Any variables defined before an include to control page generation must always be defined before we include.

Taking This Further...

We can even take this a step further and use it in other parts of our site. If you're browsing around pages and you have a right hand column with section images, we can use our if statement we used earlier to change the image being used. Use a pale image with lowered opacity for when it's not your active section and use the original image when you're browsing that section!

Interactive tweaks such as these make viewers feel more involved with their browsing experience and makes them feel they have more control over your pages.

Our final, combined code looks like this:

Header.php:
<style type="text/css">

.link {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #000;

color: #fff;

}

.link:hover {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #fff;

color: #000;

}

.link-highlight {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #434343;

color: #fff;

}

.link-highlight:hover {

display: block;

font-family: Verdana;

float: left;

padding: 4px;

background: #222;

color: #fff;

}

</style> <php

if(!isset($link_home)) {$link_home=0;}

if(!isset($link_news)) {$link_news=0;}

if(!isset($link_about)) {$link_about=0;}

if(!isset($link_links)) {$link_links=0;}

?> <a href="/" class="< ?

if($link_home > 0){

echo "link-highlight";

} else {

echo "link";

} ?>">Home</a>

<a href="/" class="< ?

if($link_news > 0){

echo "link-highlight";

} else {

echo "link";

} ?>">News</a>

<a href="/" class="< ?

if($link_about > 0){

echo "link-highlight";

} else {

echo "link";

} ?>">About</a>

<a href="/" class="< ?

if($link_home > 0){

echo "link-links";

} else {

echo "link";

} ?>">Links</a>

Index.php / News.php / About.php / Links.php
Be sure to replace $link_home with the appropriate variable on a different page to index.php.
<php

$link_home = 1;

include("header.php");

?> <p /> Blah blah blah, Waffle, Drone...