The target was to make a navigation bar like that at www.apple.com, which looks like this:

Apple navbar
They did this by having all the links share a single background image, with the x and y offsets for each set so they show the correct part of that single image. In turn the text shadowing has been done in the graphics package that made the image.
I wanted something like this that could be done using CSS, without having to handcraft a background image for each link. That’s what we’re trying to do.
Thanks to Krijn Hoetmer I had a JavaScript function which would shadow some text. But the first problem would be that I would need to put both a JavaScript link and a style sheet link in the HTML – I wanted just one link. After some Googling and experimenting I had some JS which would dynamically load a style sheet:
var cssNode = document.createElement(‘link’);
cssNode.type = ‘text/css’;
cssNode.rel = ’stylesheet’;
cssNode.href = ‘menuBar1.css’;
cssNode.media = ’screen’;
cssNode.title = ‘dynamicLoadedSheet’;
document.getElementsByTagName(“head”)[0].appendChild(cssNode);
So menuBar1.css would style the menu bar, and this JS would load it.
Next task is to shadow the text on eack link. This works by getting the div which encloses the menu, getting each of the child nodes, and calling the shadow function for each one:
var menu=document.getElementById(“menu”);
var children=menu.childNodes;
for (i=0; i<children.length; i++)
{
applyShadow(children[i], ‘white’, 3,10, 7);
}
The applyShadow function is originally by Krijn Hoetmer is modified here slightly, to handle text which has some padding (third and fourth parameters are teh left and top padding:
function applyShadow(targetElement, shadowColor, shadowOffset,pside, ptop) {
if (typeof(targetElement) != ‘object’) {
targetElement = document.getElementById(targetElement);
}
var value = targetElement.firstChild.nodeValue;
targetElement.style.position = ‘relative’;
targetElement.style.zIndex = 1;
var newEl = document.createElement(’span’);
newEl.appendChild(document.createTextNode(value));
newEl.className = ’shadowed’;
newEl.style.color = shadowColor;
newEl.style.position = ‘absolute’;
newEl.style.left = ‘0px’;
newEl.style.top = shadowOffset + ‘px’;
newEl.style.zIndex = -1;
newEl.style.paddingLeft=pside+1+”px”;
newEl.style.paddingTop=ptop+1+”px”;
targetElement.appendChild(newEl);
}
The HTML this is applying to is:
<div id=”menu”><a href=”nowhere” >Link One</a><a href=”nowhere”>Link Two</a><a href=”nowhere”>Link Three</a><a href=”nowhere”>Link Four</a></div>
This is all done in one line – any spaces or CRs produce spurious white space text nodes in the DOM tree.
This shadows the text – but we need to insert graphics for the link separators. This is a rather bizarre loop:
var count = children.length;
for (i=0; i<count*2; i++)
{
var image = document.createElement(‘img’);
image.setAttribute(’src’,'images/gap.gif’);
menu.insertBefore(image,children[i]);
i++;
}
we go for twice the number of child nodes that are there – because when we’ve finished, we’ll have twice that number. And we go i++ every time we add one. children is dynamically updated as we add nodes.
The style sheet is
#menu
{
position: absolute;
left: 20%;
right: 20%;
min-width: 32%;
background-image: url(images/linkbg.gif);
-moz-border-radius: 5px;
text-align: center;
height: 37px;
}
#menu a
{
position:relative;
color: black;
font-family: arial, helvetica, sans-serif;
font-size:11px;
padding-left: 10px;
padding-top: 10px;
padding-bottom:10px;
top:-15px;
}
The background image is 37 pixels high. We’ll only get round corners in FF – that’s IE’s problem. The result is:

My version
Works in FF and IE
leave a comment