Drop-down menu help needed

Here are the codes of a drop-down menu with javascript and css:

Html:

<head>
<title>A DOM drop-down menu</title>
<link rel="stylesheet" type="text/css" href="dropdown2.css">
<script language="javascript" type="text/javascript"
src="dropdown.js">
</script>
</head>
<body>
<h1>Menu Test</h1>
<ul id="menu">
<li class="menu"><a href="#">Home</a></li>
<li class="menu"><a href="#">Upper Body</a>
<ul>
<li><a href="#">Chest</a></li>
<li><a href="#">Back</a></li>
<li><a href="#">Shoulders</a></li>
</ul>
</li>
<li class="menu"><a href="#">Arms</a>
<ul>
<li><a href="#">Biceps</a></li>
<li><a href="#">Triceps</a></li>
<li><a href="#">Forearms</a></li>
</ul>
</li>
<li class="menu"><a href="#">Legs</a>
<ul>
<li><a href="#">Quads</a></li>
<li><a href="#">Hams</a></li>
<li><a href="#">Calves</a></li>

</ul>
</li>
<li class="menu"><a href="#">Tips</a>
<ul>
<li><a href="#">Weight Training</a></li>
<li><a href="#">Aerobics</a></li>
</ul>
</li>
</ul>
</body>
</html>

JS:

var t=false,current;
function SetupMenu() {
if (!document.getElementsByTagName) return;
items=document.getElementsByTagName("li");
for (i=0; i<items.length; i++) {
if (items[i].className != "menu") continue;
thelink=findChild(items[i],"A");
thelink.onmouseover=ShowMenu;
thelink.onmouseout=StartTimer;
if (ul=findChild(items[i],"UL")) {
ul.style.display="none";
for (j=0; j<ul.childNodes.length; j++) {
ul.childNodes[j].onmouseover=ResetTimer;
ul.childNodes[j].onmouseout=StartTimer;
}
}
}
}
function findChild(obj,tag) {
cn = obj.childNodes;
for (k=0; k<cn.length; k++) {
if (cn[k].nodeName==tag) return cn[k];
}
return false;
}
function ShowMenu(e) {
if (!e) var e = window.event;
thislink = (e.target) ? e.target: e.srcElement;
ResetTimer();
if (current) HideMenu(current);
thislink = thislink.parentNode;
current=thislink;
ul = findChild(thislink,"UL");
if (!ul) return;
ul.style.display="block";
}
function HideMenu(thelink) {
ul = findChild(thelink,"UL");
if (!ul) return;
ul.style.display="none";
}
function ResetTimer() {
if (t) window.clearTimeout(t);
}
function StartTimer() {
t = window.setTimeout("HideMenu(current)",200);
}
window.onload=SetupMenu;

CSS:

#menu {
position:absolute;
font-family: sans-serif;
font-size: 100%;
}
#menu li {
list-style-type: none;
background-color: silver;
border: 1px solid black;
text-indent: 0px;
margin-left: 3px;
}
#menu li a {
color: black;
text-decoration: none;
width: 100%; 
display: block;
}
#menu li a:hover {
color:white;
}
#menu li ul {
background-color: silver;
margin: 0px;
padding: 0px;
margin-left: 84px;
margin-top: -20px;
float:left;
}
#menu li ul li {
padding: 0px;
margin: 0px;
list-style-type: none;
text-indent: 0px;
border: 1px solid black;
float:left;
}
#menu li ul li a {
color: black;
text-decoration: none;
}
#menu li ul li a:hover {
color:black;
background-color: aqua;
}

Can anyone tell me what i have to change in the CSS file so the sub-menus appear normally when i click on the menus without the menus width expanding?I would like have the sub-menus appear on the right and out of the main menus if possible.

This is, I think, a 100% CSS question. If you turn Javascript off, you should see the problem either way, correct?

Always better to have a working HTML/CSS menu first before javascripting it all up… that way, not only does with work without scripting, but if it breaks when you add it, you know better where the problem is.

You’re not entirely clear but you have a width-less absolutely-positioned menu with floated submenus, and Javascript is making those submenus display: block and display: none.

How should anyone know their widths if you don’t say so and the main parent is absolutely positioned??

Also, why are you hiding the submenus from screen reader users? (they are aware of stylesheets, and they do honour display: none… and since they do not use the mouse, they will never get display: block)

It looks like this is a vertical menu with a right-sided fly-out?

What I would do:

Set the #menu itself to position: relative with no coordinates. This allows it to be given a z-index for if you get into trouble with IE and any relatively-positioned stuff coming after the menu. Otherwise, you don’t even need positioning at all. It’ll be a block by default and therefore will be 100% width of its container by default, so as a vertical menu, you’ll want to set a width. When you absolutely-positioned it, its width was set by the content inside, as abso-po’d and floated boxes shrink-wrap to inline-content width. This means if you have multiple words anywhere, esp with - or / in them, you should get different widths per browser as they will wrap at different places.

Set the first-level li’s to position: relative and either leave them display: block OR float them (whichever doesn’t give you a whitespace bug in IE).

The direct main-level anchors then will need to be floated to prevent IE whitespace bug. Set any floated li’s and/or anchor’s widths to 100% to be as wide as the menu and set no sidepadding/sidemargins (remove any defaults from the browser).

Now the subs:
set them to position: absolute. Their nearest-positioned ancestors are the main-level li’s, so when you set top and left (or right) on them, it will be relative to the li’s. I tend to set the Left and Top to something close to 0 and use margins for the actual placement… I think for IE’s benefit, I forget.

The submenus will be set initially to a margin-left negative number like -999px so it is off-screen yet available to screen reader users who surf with CSS on (as most people do). I set them in px so they can come onscreen with the keyboard… for some reason em’s don’t work.

When the main-level li’s are :hovered (for keyboarders, say when the main-level anchors are :focussed, + siblings come onscreen… this would be the sub ul), the left-margin position changes to a positive number (and something wider than teh width of your menu). This brings them onscreen for visual CSSers.

With the submenu’s being absolutely positioned, and their li’s and a’s inheriting float, you will likely want to set whatever width you want on the subs and you might want to remove float on the sub li’s (so they become display: block). This should stop them from stretching across the page (if that’s what they’re doing??? wasn’t clear).

Now your Javascript should only need to swap the ul.style.display for style.marginLeft = some length

You shouldn’t need to use px in the JS but you can if you have set your menu width in px. Again, I only use px on margin/coordinate settings because it seems to be the only thing that works with :focus with CSS.

BTW if you would like to see a different variation of using JS for delay on a dropdown, check this one out.
It does have a Gecko bug that’s not fixed, but it’s still useful to see what he did.