JavaScript fade menu

You can find a lot examples of JavaScript fade menu, but my goal was to make it short and simple - only 15 lines (if you don't count comment lines). First JavaScript function will initialize event listeners, while second will recursively change opacity level. It should work on FireFox and Internet Explorer.

The initialization process collects all A tags beneath TR with id="menu". I choose table, but it can be DIV as well. My first solution used getElementById method in the setTimeout recursive loop. Input parameter was object ID, but I wanted to send object pointer. Input parameter for the setTimeout can be a string or a function. No one said it couldn't be anonymous function. The trick is - when you place a function within another function, you are able to reference variables from the outer function. Means to reference and resend object pointer to the recursive call.

var opHigh = 100; // highest opacity level
var opLow  = 20;  // lowest opacity level (should be the same as initial opacity in the CSS)

// register onLoad event with anonymous function
window.onload = function (){
	//  collect menu items and attach onMouseOver and onMouseOut events
	var mi = document.getElementById('menu').getElementsByTagName('a');
	for (var i=0; i<mi.length; i++){
		mi[i].onmouseover = function(e) {fade(this, opLow,  10)} // fade in  - positive step
		mi[i].onmouseout  = function(e) {fade(this, opHigh,-10)} // fade out - negative step
	}
}

// fade in / fade out function (event handler)
function fade(mi, opacity, step){
	mi.parentNode.style.opacity = opacity / 100;                // set opacity for FF
	mi.parentNode.style.filter  = "alpha(opacity="+opacity+")"; // set opacity for IE
	opacity += step;                                            // update opacity level
	// recursive call if opacity is between 'low' and 'high' values (15ms pause between calls)
	if (opLow <= opacity && opacity <= opHigh) setTimeout(function(){fade(mi,opacity,step)}, 15);
}

Second problem was with events and nested elements. I attached event listener to the TD element and put a link inside. When mouse goes over a link, link fires onMouseOver event. Event propagates (bubbling) and TD catches event. Consequence was blinking tabs. To remove this unwanted effect, event handler should "understand" who fired event and ignore event coming from the inner element, or attach event listener to the A tag directly. In first case, JavaScript code would grow, so I rearranged CSS and attach event listener to the link. After maximising link area, blink problem has disappeared.

<table>
	<tr id="menu">
		<td><a href="#">Menu1</a></td>
		<td><a href="#">Menu2</a></td>
		<td><a href="#">Menu3</a></td>
		<td><a href="#">Menu4</a></td>
		<td><a href="#">Menu5</a></td>
		<td><a href="#">Menu6</a></td>
	</tr>
</table>
#menu td{
	background-color: #79b;
	width: 80px;
	height: 25px;
	text-align: center;
	opacity: 0.2;
	filter: alpha(opacity=20);
}
#menu td a{
	display: block;
	width: 100%;
	height: 100%;
	line-height: 22px;
	color: white;
}
#menu td a:hover{
	text-decoration: none;
}

Related posts

Bookmark and Share

3 Responses to “JavaScript fade menu”

  1. Alberto says:

    Muito bom o codigo
    Utilisei para dar fade em imagens
    so que no Mac ele nao sobrepom o texto tal como no PC
    gostaria de saber se teria como fazer sobreponha o texto no Mac
    Obrigado...

  2. dbunic says:

    @Alberto - I'm sorry but as I can barely understand you have problem with fade menu on Mac ... Unfortunately I do not have Mac near to me to test JavaScript fade menu. Hope that someone can help solving problem you mention.

  3. [...] marker. Next, I wanted a dynamic way to shade the circles. I came across a fading menu button example, which I adopted for my circles. I am not entirely happy with it, yet – you will see that [...]

Leave a Reply