JavaScript fade menu

You can find a lot examples of JavaScript fade menu, but my goal was to make it short and simple – only 20 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 in all major browsers.

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.

    // highest opacity level
var opHigh = 100,
    // lowest opacity level
    // should be the same as initial opacity in the CSS
    opLow = 20,
    // functions
    fadeIn, fadeOut, fade;

//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'),
        i;
    // loop through all elements and attach event listeners
    for (i = 0; i < mi.length; i++) {
        // fade in (positive step)
        mi[i].onmouseover = fadeIn;
        // fade out (negative step)
        mi[i].onmouseout = fadeOut;
    }
};

// mouse pointer entered
fadeIn = function (event) {
    // define link ('A' element) reference in TD
    var a = event.target || event.srcElement;
    // send TD reference
    fade(a.parentNode, opLow, 10);
};

// mouse pointer out
fadeOut = function (event) {
    // define link ('A' element) reference in TD
    var a = event.target || event.srcElement;
    // send TD reference
    fade(a.parentNode, opHigh, -10);
};

// fade in / fade out TD element
fade = function (td, opacity, step) {
    // set opacity for FF
    td.style.opacity = opacity / 100;
    // set opacity for IE
    td.style.filter = 'alpha(opacity=' + opacity + ')';
    // update opacity level
    opacity += step;
    // recursive call if opacity is between low and high values
    // (15ms pause between calls)
    if (opLow <= opacity && opacity <= opHigh) {
        setTimeout(function () { 
            fade(td, 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;
}

3 thoughts on “JavaScript fade menu

  1. 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. @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.

Leave a Comment