We originally created this for the navigation on Dragon Interactive at the end of 2006, but it has proved extremely versatile. It is, as you will see, quite simple in principle but there are many small details that are often overlooked that are essential to make the whole thing feel good.
This tutorial will walk you through creating a basic fading navigation, and provide tips to avoid some common pitfalls. In one sentence, the idea is to create a cover image and fade it in and out on hover.
The most common case is probably in a navigation of some sort, which we'll use for the example, but there are many other possibilities.
We'll be using the principle of progressive enhancement. The page should function well without any CSS or JavaScript, and then without the JavaScript, and finally as it optimally should.
The best format for a regular navigation is an unordered list containing links.
<ul id="navigation"> <li class="home"><a>Home</a></li> <li class="one"><a>One</a></li> <li class="two"><a>Two</a></li> <li class="three"><a>Three</a></li> </ul>
And include jQuery and other necessary scripts (easing, in this case) in your head, of course.
This tutorial assumes basic knowledge of CSS and building a normal navigation. First the nav should be sized and styled using just CSS, as it would otherwise. Optionally you can implement normal CSS based :hover effects, for the 0.05% of people that don't use JavaScript. The classes are applied on the li's to match with body classes for displaying the current page.
The most basic example is with a full image based navigation, where the text is part of the image and the actual text is hidden. This has a few benefits, one of the greatest being the font styling and anti-aliasing possible. This can be seen at the top of Dragon Interactive, as well as many other sites. The text can be hidden with either a high negative text indent or wrapping with a hidden span. The use of a sprite is highly recommended.
We do need extra code to make it work, but since the new markup is only going to be used for the effect so we can just insert it using JavaScript and keep everything neat. jQuery makes it absurdly simple to do so.
$('#navigation li a').append('<span class="hover"></span>')
<ul id="navigation"> <li class="home"><a>Home</a><span class="hover"><span></li> <li class="one"><a>One</a><span class="hover"><span></li> <li class="two"><a>Two</a><span class="hover"><span></li> <li class="three"><a>Three</a><span class="hover"><span></li> </ul>
As you can see, there is just an extra span.hover at the end which we will be fading in and out on hover.
We need to add a few styles to get the hovers where we want them...
#navigation a { position: relative; }
#navigation a .hover {
display: block;
opacity: 0;
position: absolute;
top: 0;
left: 0;
height: 100%;
width: 100%;
}
Naturally, the hover span should have the background image applied so that it lines up properly with the image that is the background of the link.
First we'll setup our basic hover function.
$('#navigation li a').hover(function() {
// Stuff that happens when you hover on
$('.hover', this).animate({
'opacity': 1
}, 700)
},function() {
// Stuff that happens when you unhover
$('.hover', this).animate({
'opacity': 0
}, 700)
})
This will animate the .hover to an opacity of 1 (a "fade") in 700ms when its parent link is hovered. Then when hovered off of, it will animate it back to an opacity of 0, effectively hidden again.
One of the common problems people have is that they don't use a .stop() function. Without it, the effect will go through its entirety each time it is triggered, and mousing on and off a few times will set up a long queue. This is generally not desirable, so we have it cancel any previous animations anytime you hover on or off. This works extremely well and makes the whole thing feel quite responsive.
$('#navigation li a').hover(function() {
// Stuff that happens when you hover on + the stop()
$('.hover', this).stop() .animate({
'opacity': 1
}, 700)
},function() {
// Stuff that happens when you unhover + the stop()
$('.hover', this).stop() .animate({
'opacity': 0
}, 700)
})
We will fill in the hover functions with animations of the opacity of the hover spans. For more details, see the animate effect documentation.
This is generally where most of the 'Dragon Interactive nav' tutorials stop. But at this point, it still wouldn't feel right. The animation is a plain linear one. And the random timings we picked earlier probably aren't that great. To really make everything feel smooth, we need more control than just the timing (though that is an important variable as well). We need to change the shape of the opacity curve.
Fortunately, there is a great easing plugin available for jQuery. After including the script, you can use a whole set of different easing options.
$('#navigation li a').hover(function() {
// Stuff that happens when you hover on + the stop()
$('.hover', this).stop() .animate({
'opacity': 1
}, 700, 'easeOutSine')
},function() {
// Stuff that happens when you unhover + the stop()
$('.hover', this).stop() .animate({
'opacity': 0
}, 500, 'easeOutExpo')
})
While there are a whole slew of different ones to choose from, we generally end up using easeOutExpo, easeOutSine or easeOutQuint for things like this. Your mileage may vary, though, and a big part of these types of effects is just testing and calibrating so feel free to try out some of the different options and experiment a bit.
Also notice, the timings and easings for the two animations (in and out) do not have to be the same. While it may work out that the easing is best the same both ways, it'd probably be better to have the timings slightly asymmetrical. I can't stress how important proper testing and calibration is for effects like this. It's not just a boolean thing, where you have fades and your site is 50% cooler.
There are three variables that need to be set: the image, the speed, and the easing. Note that changing the easing type may change how effective the speed is as well. And having a slight difference between images will probably require a faster speed than one where the image is drastically different.
How to design a good navigation is beyond the scope of this article, but for this to work well it is very important to have some good images to work with. If the navigation sucks without fades, it's not going to magically become good once things start fading. Adding on more effects and layers of complexity requires even more design time and testing. Expect to spend a while testing and tweaking the images and timings to really make it feel good.
Avoid fading between two opposite colors, for example fading a blue button to red. At the 50% mark they will cancel out and you'll get an odd shade of grey.
And again, you should be using sprites whether or not things are fading.
The effect should be bold enough to be noticeable, but yet not so much that it's annoying. There are a lot of possibilities, from basic glows to changes in shape, depth or lighting (as if a button is being pushed in, for example).
Browsers have come a long way, and the latest Safari and Firefox are quite good at doing a lot of animations very smoothly. But people use other browsers, and even the latest Firefox can be a bit jumpy in some cases (like when there is a lot of content on the page or it's an intense animation) so keep that in mind when building effects. Unfortunately some things may be too intensive to run smoothly enough. In some cases it might be wise to specify different settings for different browsers—for example safari gets a longer animation than other browsers because it is the only one that can handle it. Of course we have to hope they're using the latest version and not a pre-Tiger build for it to run smoothly. Still, it's a decent assumption.
On the other hand, some browsers will perform so appallingly that you will probably want to cry. This technique, using only basic positioning and opacity, will work even in IE6. But there might be instances where it doesn't—or has some sort of issues. It may be possible to ameliorate the issue by changing timings, or else just ditching the effect altogether and returning true for that one browser that causes issues. jQuery has pretty good browser sniffing capabilities that can differentiate between all the different engines.
Shadows and highlights are a complex topic, but avoid creating divisions of low contrast. A common mistake I see is having a shadow that ends up being lighter than the background, or halfway in between the foreground and background—so the edges just end up looking real fuzzy.
The Dragon Interactive navigation gets around this issue by covering up the shadow on the adjacent left button with a new highlight upon hover. This gives a nice sharp edge to what would otherwise be a weird blurry line between the old shadow and the newly darkened edges of the hover. The same idea is used at the tops of the side menu hovers.
#1 in the above figure shows how it would look with just the button replaced with the hover—the shadow of the above button combines to make everything a bit blurry. #2 shows the difference with the extra highlight added.
Another solution is to use 3 lines of shadows and highlights, instead of the typical 2.
We may do a full article on the subject later, as it's something even the best designers seem to have trouble with.
Though this article is about fades, the same principles can be used for all types of effects. Some other possibilities are motion (like on noisefreak) or fading out all the other items (like on the homepage
We hope you enjoyed the tutorial and found it useful in some way.
Any questions can be posted in the discussion and you're encouraged to post your implementations there too! We'd love to see what you make of it, and it'll save us the trouble of making a bunch of demos ourselves.
Follow us on twitter: @dragonlabs