RSS Feed

I recently stumbled upon Dragon Interactive (dragoninteractive.com).  It’s a pretty well designed site.  However, the pièce de résistance is their rather cool animated menu.  Now…  had this been designed in Adobe Flash, I wouldn’t had paid much attention.  A closer inspection revealed that the menu is plain XHTML, CSS and Javascript.  Today, I’m going to show you how to create an animated menu (very similar to Dragon Interactive’s menu).



Designing The Sprite

To begin with, you will need to build your design in Adobe Photoshop - or some other illustration program.  You will need to design a sprite.  I also quickly designed a repeating background image (just to make things look pretty):

Sprite Screenshot

The XHTML Markup

Here is the XHTML markup that is used in the demo:

<ul id="menu">
	<li><a href="#" class="home"><span></span></a></li>
	<li><a href="#" class="portfolio"><span></span></a></li>
</ul>

As you can see, an unordered list is used to structure the menu.  In this tutorial, I’m only going to create 2 links.  You can add as many links as you desire.  Notice that each link is given a unique class.  We will need to work with each class individually when we write the CSS.

The CSS

For the demo, I assigned the repeating image as a background image for the <ul> element.  I also set the height and width:

ul#menu {
width:80%;
height:102px;
background:url(bg.png) repeat-x;
list-style:none;
margin:0;
padding:0;
padding-top:20px;
padding-left:20%;
}

Notice that in the above CSS, “list-style:none;” is used to prevent styling the list using the default bullet point format.  The rest is pretty self-explanatory.  We will now need to float each <li> element so that the list elements are displayed horizontally rather than vertically:

ul#menu li {
float:left;
}

Now we get to the good stuff!  We’re going to need to add the sprite as a background image to each link in the menu.  However, we only want to display a section of the sprite for each link.  We do this by restraining the link to some specified dimensions and then positioning the background image accordingly.  Let’s look at the following sprite:

Sprite

Each column represents a different link.  In this case, we only have 2 columns since we only want 2 links.  The bottom row defines how the link will look when you hover over it with your mouse cursor.  Now, say we define the link to have a height of 81px and a width of 159px.  If the background image is then positioned to the top left, we see that only the “Home” button is displayed:

Sprite Dimensions

This is because the “Home” button was designed such that it has a height of 81px and a width of 159px.  As the background is positioned to the top left, this is the only part of the image that will fit inside the link - which is obviously when we want! So, how do we write this using CSS?  Well… first you will need to recognise that in most cases, we will want more than a single link (in this case - 2 links).  Hence, it is easier if we write some common CSS for all the links (i.e. CSS that may be inherited by each and every link in the menu).  We can always add to (or overwrite) these common CSS attributes by later writing CSS for each specific class assigned to the link (see XHTML markup).  Here is the common CSS that is used in the demo:

ul#menu li a {
background:url(sprite.png) no-repeat scroll top left;
display:block;
height:81px;
position:relative;
}

In the above code, we position the background image to the top left.  This is fine for the “Home” link.  However, for the “Portfolio” link, we will need to overwrite the background position attribute for concerning class (see XHTML markup).  Please also note that we define the height here since all the links will have the same height.  As links by default are displayed inline, we must use “display:block” to specify the height of the link.  Finally, we must position the link relatively.  It will become apparent why we need to do this later.

We will now need to write some CSS for each individual link.  We do this by specifying the class (see XHTML markup).  This tutorial deals with just 2 links.  The “Home” link has the class: “home”.  The “Portfolio” link has the class: “portfolio”.  We can hence define CSS attributes for each individual link as follows:

ul#menu li a.home {
width:159px;
}
ul#menu li a.portfolio {
width:157px;
background-position:-159px 0px;
}

Notice that it is here where we specify the width of the links (since each link may have a different width according to the design).  It is also here that we overwrite the background position attribute if needed.  We do not need to do this for the “Home” link since the common class already has this defined as “top left”.

We will want to position the sprite differently for the “Portfolio” link.  Since the “Home” link is 159px wide, we will need to shift the background position 159px to the left in order to focus on the “Portfolio” area.  We do this by writing “background-position:-159px 0px;”.  This tells the browser to shift the background 159 pixels to the left and 0 pixels down.  You can learn more about positioning background images using CSS over at SitePoint.

Sprite Dimensions

We now need to create the “hover” state.  This is how the link will appear when you hover over it with your mouse cursor.  The animation will blend between the 2 states.  To create the hover state, we’re going to use a <span> tag.  We’ll then use CSS to have that span tag completely fill the link (so that it is exactly the same size as the link).  We’ll also need to shift the background image down for the span in order to display the “hover” area of the sprite.  As before, we’ll use some common CSS:

ul#menu li a span {
background:url(sprite.png) no-repeat scroll bottom left;
display:block;
position:absolute;
top:0;
left:0;
height:100%;
width:100%;
z-index:100;
}

Note that we again use “display:block;” since, by default, the <span> tag is displayed inline.  Now that the <span> is displayed as a block, we can define the height and width to 100% - completely filling the link (so that the span and link are exactly the same size).  Also notice that we position the <span> absolutely inside the relatively positioned link.  Positioning the <span> in this way allows us to define a z-index.  The assigning a high z-index ensures that the span’s background is displayed above the link’s background.  All that we are left to do is position the background for the <span> tags (contained within the links):

ul#menu li a.home span {
background-position:0px -81px;
}
ul#menu li a.portfolio span {
background-position:-159px -81px;
}

Notice that we shift the background down by 81 pixels for each span tag (since the height of the “Home” link is 81px).  This causes the “hover” state to be displayed within each span tag.  As before, we also shift the background left by 159px for the “Portfolio” link.

Using jQuery For The Animation

The animation is really quite simple.  We’ll use jQuery to animate the opacity of the <span> tag.  Remember that the <span> tag displays the “hover” state of the image.  Hence, when the <span> is visible, the link takes the “hover” appearance.  We’ll need the “hover” state to be invisible when the page loads.  We can do this by setting the opacity of the <span> tag to “0″:

$(function() {
// set opacity to nill on page load
$("ul#menu span").css("opacity","0");
// the rest of the code will go here
});

Placing the code inside of “$(function() { … });” tells the browser to execute the code when the document has loaded.  The code that we’ll use to do the animation is as follows:

// on mouse over
$("ul#menu span").hover(function () {
// animate opacity to full
$(this).stop().animate({
opacity: 1
}, 'slow');
},
// on mouse out
function () {
// animate opacity to nill
$(this).stop().animate({
opacity: 0
}, 'slow');
});

Hence the entire Javascript used is as follows:

<!-- Include jQuery Library -->
<script src="jquery-1.2.2.pack.js" type="text/javascript"></script>
<!-- Let's do the animation -->
<script type="text/javascript">
	$(function() {
		// set opacity to nill on page load
		$("ul#menu span").css("opacity","0");
		// on mouse over
		$("ul#menu span").hover(function () {
			// animate opacity to full
			$(this).stop().animate({
				opacity: 1
			}, "slow");
		},
		// on mouse out
		function () {
			// animate opacity to nill
			$(this).stop().animate({
				opacity: 0
			}, "slow");
		});
	});
</script>

Notice that we first include the jQuery library.  You can learn more about jQuery animations by reading up on the documentation. One final addition to the CSS is required to ensure that the mouse cursor is display as a pointer when hovering over the <span> tag:

ul#menu li a span:hover {
cursor:pointer;
}

The full source code can be accessed via the demonstration page.  I should just add that whilst this code seems to work well with FireFox and IE7, IE6 might (and probably will) be a different story.