Watch the image fade revisited screencast (alternative flash version)
QuickTime version is approximately 30Mb, flash version is streaming.
View the demo and source code used in the screencast
Also a side note about IE6 support:
Side note: IE6 screencast (alternative flash version)
Understanding the Problem
So let’s break this down and see how it’s done.
The first thing I look for when understanding how a web effect has been achieved, is to look at what they’ve done when JavaScript is disabled. Where possible, I always want to produce a solution that works cleanly without JavaScript enabled.
Since Dragon Interactive are using the effect for navigation, as I suspected, the effect degrades to…nothing. Although we’ll take it one step further by creating a hover state for the navigation.
The second thing I’ll look at is the difference between the sent markup and the rendered markup. This gives me the clues I need to understand what’s going on behind the scenes without having to read their JavaScript.
The key in their version is there is a new span within the hover area that isn’t in the sent markup. So this is what’s being created using JavaScript, and this is also the key to the whole effect.
From this, we can see when the anchor is hovered over, the newly created span’s opacity is faded up and completes the transition effect.
HTML
Note that our default HTML has this extra class="highlight" because I want the hover effect to still trigger if JavaScript is disabled. We’ll strip out this class in the jQuery later on. It also means we’ll have slightly more CSS to support both the hover state and the jQuery based hover state.
Also, everything with the anchor will be hidden due to the #navigation a * { display: none; } rule. This means with CSS turned off the navigation still works.
<ul id="navigation">
<li class="highlight"><a href="#" class="home"><span>Home</span></a></li>
<li class="highlight"><a href="#" class="services"><span>Services</span></a></li>
<li class="highlight"><a href="#" class="portfolio"><span>Portfolio</span></a></li>
<li class="highlight"><a href="#" class="about"><span>About</span></a></li>
<li class="highlight"><a href="#" class="contact"><span>Contact</span></a></li>
</ul>
CSS
This is only a snippet of the CSS (for full CSS see the working example). We’re using a CSS sprite and changing the background position both in the a:hover state and for the jQuery create span.
#navigation a * {
display: none;
}
#navigation a,
#navigation a .hover {
height: 70px;
position: relative;
display: block;
background: url(images/dragon-sprite.jpg) 0 0 no-repeat;
}
#navigation a.home {
background-position: 0 0;
width: 102px;
}
/* .highlight will be remove if JS is enabled */
#navigation .highlight a.home:hover,
#navigation a.home .hover {
background-position: 0 -280px;
width: 102px;
}
jQuery
Finally, all that’s left is to create the new span and fade it up and down when we hover over.
$(function () {
// IE6 doesn't handle the fade effect very well - so we'll stick with
// the default non JavaScript version if that is the user's browser.
if ($.browser.msie && $.browser.version < 7) return;
$('#navigation li')
// remove the 'highlight' class from the li therefore stripping
// the :hover rule
.removeClass('highlight')
// within the context of the li element, find the a elements
.find('a')
// create our new span.hover and loop through anchor:
.append('<span class="hover" />').each(function () {
// cache a copy of the span, at the same time changing the opacity
// to zero in preparation of the page being loaded
var $span = $('> span.hover', this).css('opacity', 0);
// when the user hovers in and out of the anchor
$(this).hover(function () {
// on hover
// stop any animations currently running, and fade to opacity: 1
$span.stop().fadeTo(500, 1);
}, function () {
// off hover
// again, stop any animations currently running, and fade out
$span.stop().fadeTo(500, 0);
});
});
});
You should follow me on Twitter here I tweet about jQuery amongst the usual tweet-splurges!
Related screencasts
Demo
If you find this demo doesn't work as expected, it's possibly due to the demo running from within an iframe. Try running the demo in it's own window.
Source Code

Play QuickTime version
Play Flash version

Joel Birch On 28th July 2008 at 13:07
Just lovely - thanks for this. I so appreciate techniques that degrade this flawlessly.
Jeff On 28th July 2008 at 14:07
Thanks so much for this. I was following your discussion with Greg, and I’m so glad to see this clean description hit your site. Very helpful for js & jquery newbies like myself. Your blog is a staple in my RSS reader.
Thanks again!
Travis Phipps On 28th July 2008 at 14:07
I loved watching the tutorial screencast. It was great to see your train of thought as you worked on the problem, and even more encouraging to see a great jquery developer making the same mistakes I make (and following the same processes to find and fix them).
As you said in the video, I’m sure you prefer to put out flawless videos, but I’d like to encourage this type of video that really helps the audience identify with the presenter!
Anup On 28th July 2008 at 14:07
Very neat. Might be worth extending very slightly by handling focus/blur events so keyboard users will get the same effects when tabbing through.
Not tried it locally, but I think you can just add .focus and .blur events, and if you make the hover function handlers into separate functions you can just call them from focus and blur events too.
Yereth On 28th July 2008 at 15:07
Excellent effect and whoever was first in coming up with the technique: kudos!
But wasn’t this effect available on http://ui.jquery.com/ for a while now as well? Or was Dragon first?
Greg Johnson On 28th July 2008 at 16:07
ui.jquery thank Dragon Interactive in their source code for coming up with the effect.
Having this method was very important to me, so I’m very grateful for the help.
I used it to develop a free WordPress theme. It’s not officially released yet, but have a sneak peak at the wp coda theme.
Felix On 28th July 2008 at 16:07
Wow wicked cool! Thankssssssssssssssss a zillion.
web artchitect newbie On 29th July 2008 at 08:07
It seems flash :) Thank you for sharing these great tutorials Greetings from Italy
Jeremy On 30th July 2008 at 08:07
This was amazing, I was looking for something like this for a long time now!…
I just have one more question about it, which by the way I have already tried finding out a solution but couldn’t, and it is the “CURRENT” state of the button. The page that we are currently on has a different color of fade. I believe this new position of the buttons large image comes from the CSS, but how do I test the current page and execute that particular piece of code?….
Thank for the help in advance!
Jeremy
Bart On 4th August 2008 at 12:08
thnx for ur awesome tutorials :)
Misha On 5th August 2008 at 21:08
Thank you for the screencast.
BaRzO On 6th August 2008 at 14:08
Thanks for your nice screencasts. They are really very nice and useful Thanks a lot…
Andrew On 6th August 2008 at 15:08
Hi, I’m using fading script in big logo-image. How can I fadeTo (and off) random background areas while page is loaded? - Without interruption; one after another and only one element in the same time. Greetings.
caruso_g On 10th August 2008 at 20:08
Another wonderful screencast, a lot of things more learned. Every time a discovery. Thanks.
PresenceLayer On 12th August 2008 at 08:08
I have something like this that works (well) in IE6: http://okb.no Not quite made for release, but works perfectly in all major browsers as set up on our site.
Jay On 21st August 2008 at 12:08
heya buddy. Awesome tutorial, and a stunning effect.
i was just wondering if you could help me make it a little more awesome…. I want to achieve the same effect, but retain the text. So that I don’t have to render an image (or 2) with the text in the image, I want to create 1 button, and then use the html of the anchor to do the text.
This would mean that that button is then re-usable for most buttons in a design, without having to re-render a new image every time you want the button to say something different!
Any help appreciated, I think I’m nearly there, but this would make the technique invaluable!
Cheers
Jay
Ryan J On 25th September 2008 at 13:09
Hi I have an issue! please bare with me since I am very new to this whole web dev thing. I was wondering how I can make <li> stay to the left of the page? since I include this navigation into my my template with php include..it messes up the entire template display because the navigation starts off a bit away from the left side of the page!
Any help would be appreciated.
Thank you! Ryan .J
Rahul Joshi On 28th September 2008 at 17:09
How can i highlight the selected link for a particular page using this style of menu?
Jeremy On 10th October 2008 at 07:10
I had the same question… Anybody please? Thank you
Michael Turner On 20th October 2008 at 15:10
I adapted your code for a test page located at architerra.com/damask2.lasso (to be inserted into a frame once live.) It works fine in Firefox, but nothing renders at all in Safari. I have compared our code - yours works in both - and cannot nail down what is going wrong.
Can anyone else see the problem?
kelvin On 2nd November 2008 at 14:11
Hi,
FINALLY! i found this great link…
Actually i would need some help actually..i need to have prototype and scriptaculous in my website but i would love to use your script.
Is it possible that you tell me how you can use jQuery.noConflict(); here in this case?
I know i have to substitute “$” to jQuery but everytime i put the code ” jQuery.noConflict(); ” it disables the whole website. I dont know what’s wrong!
Would be glad if u can help. thanks!
brandon On 8th December 2008 at 00:12
Hey Kelvin I have been trying to figure this out all day too but I just figured it out here is the code i used from my website:
hope that helps. I placed it last im my also. I’m pretty new to java so i dont know if placing the code at the end would make a difference but it seemed to.
web designer On 10th December 2008 at 23:12
I am trying to use it with a transparent PNG imagel works great on FF but on IE7 the hover image looks funny the transparent png doenst look clean any idea why the png is not clear ?
criss1one On 19th December 2008 at 20:12
great work!But how do i find the dragon-sprite image.help please!
Richard On 4th February 2009 at 09:02
I’ve been using this code for a site I’m working on now and found that this code will overwrite the normal function to enable an ‘on’ state. I’m sure there’s proabably a better way, but in an case this works in FF2+, IE6+, Safari 3 (mac+pc), Opera 9 (mac+pc) and Chrome.
Just give the list item an extra class of ‘here’
Your css requires just one addition to make it work (the top declaration - #navigation a.here - is the addition):