Color Fading Menu with jQuery

Published by Guest Author

Editor's note: When I first pushed out this latest redesign for CSS-Tricks, it featured a simple color fading animation in the main navigation. Liam quickly noticed a flaw in the code I was using to do it, where if you very quickly moused back and forth over the menu items some of the transitional color would "stick". Liam generously rewrote the code to be a bit smarter for me, and I asked him to write this tutorial. Thanks Liam!

Hello, I am Liam Goodacre, and Chris has asked me to write a short jQuery tutorial on how to achieve fading hover effects. I will demonstrate how to perform colour and image merging. We will be using jQuery and the jQuery Colour plugin.

When I first wrote something like this, I set a background div to fade in on mouse hover, and fade out on mouse leave. I found that if I quickly moved my mouse over and out of the link, then the background kept flashing the same number of times as my mouse. I then told the animation to stop before I set new animations, this solved the problem, but produced a new one.

The new problem: if I did the same test (repeated mouse hovering), then the link's mouse out state, would slowly look the same as the hover state, therefore the background stopped fading out after a few times. I noticed that Chris had this same problem on his site.

I then had an idea; on mouse hover, if I stopped the current animation, and reset the background to be invisible, then fade it in, rather than starting it fading from its current state. This seems to have solved the problem.

View ExampleDownload Files

Ok then, let's get started...

What we need is a div containing two things; an anchor element and another div, which I will refer to as the subDiv. The subDiv will display the image that will fade in on mouse hover. The Anchor will overlap the subDiv and have a transparent background.

The HTML

We will add the subDiv to the div dynamically using jQuery, to reduce the ammount of html we need to write. This is helpful, when having multiple links like this.

This is our html code so far...

<div class="hoverBtn">
	<a href="http://css-tricks.com/">Go to CSS-Tricks</a>
</div>

We have a div with a class of hoverBtn containing and a link to CSS-Tricks.

The CSS

div.hoverBtn {
	position: 		relative;
	width: 			100px;
	height: 		30px;
	background:		#000 url(your_background_image.png) repeat-x 0 0 scroll;
}
div.hoverBtn a {
	position: 		relative;
	z-index: 		2;
	display: 		block;
	width: 			100px;
	height: 		30px;
	line-height: 		30px;
	text-align: 		center;
	color:			#000;
	background:		transparent none repeat-x 0 0 scroll;
}
div.hoverBtn div {
	display:		none;
	position: 		relative;
	z-index: 		1;
	width: 			100px;
	height: 		30px;
	margin-top: 		-30px;
	background:		#FFF url(your_hover_image.png) none repeat-x 0 0 scroll;
}

The subDiv is now positioned underneath the anchor, and I have applied background graphics to the div and the subDiv.

The JavaScript

I am going to assume you have a basic understanding of how to use jQuery, although, even if you don't, the code is pretty much self explanatory.

Here is our starting point...

//when the dom has loaded
$(function(){
	
});

I'm sure most of you are all fully aware, any code written within these two lines, will run as soon as the DOM has finished loading.

We now need to add the subDiv. Which we an accomplish by using the 'append' method of jQuery objects.

//when the dom has loaded
$(function(){
	//display the hover div
	$("div.hoverBtn").show("fast", function() {
		//append the background div
		$(this).append("<div></div>");
	});
});

I have wrapped the 'append' within the call-back of the show method, so that we can use 'this' to reference each div.hoverBtn element.

Now we need to code the link's hover event. We will fade the font colour, therefore we should specify a hover colour. We can also use the 'rel' attribute to store the initial colour of each anchor. This is useful for different coloured links.

var hoverColour = "#FFF";
//when the dom has loaded
$(function(){
	//display the hover div
	$("div.hoverBtn").show("fast", function() {
		//append the background div
		$(this).append("<div></div>");
		//on link hover
		$(this).children("a").hover(function(){
			//store initial link colour
			if ($(this).attr("rel") == "") {
				$(this).attr("rel", $(this).css("color"));
			}
			//fade in the background
			$(this).parent().children("div")
				.stop()
				.css({"display": "none", "opacity": "1"})
				.fadeIn("fast");
			//fade the colour
			$(this)	.stop()
				.css({"color": $(this).attr("rel")})
				.animate({"color": hoverColour}, 350);
		},function(){
			//fade out the background
			$(this).parent().children("div")
				.stop()
				.fadeOut("slow");
			//fade the colour
			$(this)	.stop()
				.animate({"color": $(this).attr("rel")}, 250);
		});
	});
});

So basically, what happens is;

  • A hover colour is declared
  • When the DOM has loaded...
  • A subDiv is appended to the hoverBtn div
  • On the hover event of the link:
    The initial colour is stored within the link's rel attribute
    The subDiv's animation is stopped
    It is hidden and then set to fade in
    The link's animation is stopped
    It's colour reset and set to fade to the hover colour
  • On the hover event's call-back:
    The subDiv's animation is stopped
    It is then set to fade out
    The link's animation is stopped
    It is then set to fade to it's initial colour

Further developments

You could try to improve this by dynamically loading the containing div. Which might also involve setting the containing div's size to that of the anchor element.