Forum Moderators: open

Message Too Old, No Replies

The theory behind drop down menus

         

AffiliateDreamer

6:14 pm on Jun 17, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi,

Can someone explain to me the theory behind creating a javascript dropdown menu, but the menu is created from html/css markup.

meaning:

<ol class=menu>
<li>blah</li>
<li>category2</li>
</ol>

Maybe if someone could just discuss, at a high level what needs to be done I can understand the theory behind it.

thanks!

lavazza

6:52 pm on Jun 17, 2008 (gmt 0)

10+ Year Member



As someone who used to use dropdown (and flyout) menus, my hunch (not quite a theory) is that, most of the time, developers implement them for the same reasons that dogs lick their nether regions: because they can

I stopped using them when I remembered what the I in IT stands for, realising that (although implementing such menus might prove that I can copy and paste HUGE chunks of code) such menus are unlikely to INFORM visitors in an efficient manner - which is, I think, "what needs to be done"

AffiliateDreamer

7:56 pm on Jun 17, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



*confused* :)

I'm talking about the theory in terms of technically, how one goes about creating these types of menus using javascript. (I want to understand the theory, then try and read some sample code that creates menues)

eelixduppy

2:52 pm on Jun 18, 2008 (gmt 0)



You are talking about two different things. There are ways of making these menus with javascript, and then there are CSS only solutions. Which are you referring to and which do you want to learn?

rocknbil

6:58 pm on Jun 18, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Since no one else has offered, here is my version of the "theory" behind drop-downs.

I like to create semantic lists as shown that are initially hidden. Depending on the content of the nav lists, you can activate and position these lists using CSS or Javascript.

The lists actually exist on the page at load so that they index as links. Depending on the conditions, I use one of two approaches. For most "horizontal top-navs" I use a nested list as in the example below, or in the case where these menus can be located "anywhere" on the page (as in a drop-down when a part of an image is moused over or clicked,) I usually I have them follow page content:

<p>content</p>
<ul class="menuitem" id="menu1">
<li><a href="#">Menu 1</a></li>
</ul>
<ul class="menuitem" id="menu2">
<li><a href="#">Menu 2</a></li>
</ul>
..........

The initial load of these lists are assigned display:none or positioned adequately off the page to the left. I've played with both, and depending on the conditions, don't really use one more than the other.

The choice of CSS-only or Javascript driven drop downs are going to largely depend on what's in these lists. The best choice is to try to use the a:hover selector to drive your menus. For the case of a button with an image-based mouseover/mouseout state, the initial background would load, then on hover you change the background attribute of the anchor (not list item, see below.)

You want to rely as heavily on CSS and as lightly on Javascript as possible. You want these things to either work or degrade gracefully depending on whether or not Javascript is enabled. The more your menus rely on CSS, the closer to this goal you will be.

The hover state of the visible link or main navigation is what sets the visibility (or positioning) of the hidden drop down. When those become visible, the hover state of the menu items changes the backgrounds. This has the advantage of allowing you to use a text content in the menu item instead of an image, a definite plus for SEO, but presents some problems mentioned in positioning below.

There's a fundamental problem with CSS-only menus you've probably already guessed - when you mouse out of the visible menu item to mouse over the now-visible list, it causes the hover state of the base menu to cease, causing the drop down to disappear before you can get your mouse to it. This, and the case of graphic buttons, is where you need Javascript.

You can minimize the Javascript you need by using it only to manage the mouseovers with setTimeout() or by setting a variable for this particular drop down. For example,

<ul class="menuitem" id="menu1">
<li><a href="#" onMouseOver="MouseIsOver=1;" onMouseOut="MouseIsOver=0;">Menu 1</a></li>
</ul>
Of course, you would make these functions unobtrusive and in an external file, shown inline for example only.

In your Javascript function, you set a timeout to make all lists styles revert to display:none if the mouseOver variable is 0 for more than "X" seconds. You combine this effect with the mouseover events of the other menus - on mousing over a new one, it closes all others.

The effect is that a menu will remain visible for a second or two while the mouseOver variable is set to 0. This gives the user time to get from the link that opens the menu to the menu itself. In reality, as soon as the user "leaves" a menu, other parts of your mouseover function effectively turn it off. The only time it would stay open for a second or two is if the user moves the mouse below and away from the menu and doesn't cross over other menu items.

Positioning: I've managed to avoid absolute positioning completely. I learned early on this invites so many cross browser and monitor compatibility issues it's more trouble than it's worth. Since CSS positioning is relative by default, it's REALLY easy to set up a semantic menu without any special positioning at all:


<ul id="main-nav">
<li><a href="#">Features</a>
<ul>
<li><a href="#">Costs</a></li>
<li><a href="#">Specs</a></li>
</ul>
</li>
<li><a href="#">Contact</a>
<ul>
<li><a href="#">Sales</a></li>
<li><a href="#">Support</a></li>
</ul>
</li>
</ul>

Aside: in real life you would remove ALL WHITE SPACE between list items. IE has this bug that would cause an unexpected space between them if you don't.

The above nested menus are already where you want them. All you need to do is display the main menu list items inline and float them all left, and the nested UL's will go wherever the main-nav is positioned. You can center the entire nav chunk, flush it to one side or the other, whatever. I've found working this way instead of using absolute positioning eliminates a lot of headaches. You will spend some time wrangling with what to do about the width, especially if you use text content for the link. As you know, assigning a size to the text link can be a slippery beast - pixel sizing doesn't always work, and end user's browser settings can sometimes cause your menus to explode. This is the best case for using graphic-based navigation elements.

Correct assignment of mouse-over: Some designers visualize their menus as the list items themselves, not the anchor, and sometimes try

<li onMouseOver="someAction();">

Some browsers react correctly to this, some do not. For this reason it's a good idea to always use the natural object for the mouseOver event - the anchor. If you style your anchor and apply any mouse-over actions to it, a lot of these problems will go away.

The way I build a drop-down menu for a horizontal navigation:

- Start with the HTML. Build a semantic list as above, at this point it dances down the page with bullets, unstyled.

- Go at the style sheet, remove margins, padding, make the parent navigation list items inline, float them left, let the nested menu items fall where they may. So what you should have at this point is a horizontal navigation with all the drop downs visible, but are now positioned below the "main nav" links across the page. At this point, they will likely "cover up" the main navigation links; add margin to the top of the nested UL class to bump them down.

- Go at the styling and hover states of the drop-down list items, but I start with the anchors (see comment above.) These are my "containers" that react to mouseover states, not the LI's. I style them appropriately, padding them out, making sure all the paddings and colors work the way I want.

- Now I set the display of these items to none and write an external unobtrusive function for the parent items to open the drop downs.

Since you asked for theory, I won't paste examples in this post, but there are millions of them out there. :-) I can come back with code (as time allows!) if you would find it helpful.

There **IS** one other method widely in use on the 'net - I mention it here only so you can avoid it. There is an old method using only Javascript that uses document.write() to write out the menus each time the object is moused over. In the cases of small menus, this "works." But as soon as you get more than 20 on a page, it begins to suck up memory like you wouldn't believe, causing the whole page load to slow to a halt. Avoid this method at all costs.

WHY WOULD YOU NEED MORE THAT 20 MENUS ON A PAGE? I took over a project with an illustration that required clicking over 100 points in the illustration, each to open a menu . . . long story . . . but the CSS/JS method used above fixed it.

[edited by: rocknbil at 7:13 pm (utc) on June 18, 2008]

buckworks

7:11 pm on Jun 18, 2008 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



I can come back with code (as time allows!) if you would find it helpful.

Find it helpful? Yes, yes, YES! :)

rocknbil

7:34 pm on Jun 18, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



LOL . . . well like I said, millions out there. Here's one I cobbled together on demand, many of you will recognize the base elements of the Suckerfish menus. It doesn't use the timeout stuff I talked about, running a bit late at the moment and can't locate an instance of that solution (now what project was that?). . . .

This is the basis of a horizontal nav with drop-downs.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!-- doctype always on one line -->
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Menu Sample</title>
<style type="text/css">
body { padding: 0; margin: 0; }
#main_dd,#main_dd ul {
margin-left: 20%;
margin-top:0;
list-style: none;
white-space: nowrap;
}
#main_dd li a {
display: block;
padding: 0px 6px 2px 6px; /* T R B L */
}
/* main horiz.list items */
#main_dd li {
float: left;
white-space:nowrap;
padding: 0px;
}
/* list items */
#main_dd li ul li {
width: 11em;
text-align: left;
border-bottom: 1px solid #ddc1d1;
}
#main_dd li ul li a {
display: block;
width: 11em;
w\idth: 10em; /* Opera hack. ACK! */
padding: 0px 6px 2px 6px;
}
#main_dd li ul {
position: absolute;
width: 11em;
left: -999em;
padding: 0;
margin: 0;
}
#main_dd li:hover ul, #main_dd li.sfhover ul {
left: auto;
background-color: #ebe2ea;
border-top: 1px solid #043219;
border-right: 2px solid #043219;
border-bottom: 2px solid #043219;
border-left: 1px solid #043219;
}
#main_dd a:hover { background-color: #043219; }
#main_dd ul a:link { color: #043219; font-weight: 700; text-decoration: underline; }
#main_dd ul a:visited { color: #3B532E; font-weight: 700; text-decoration: underline; }
#main_dd ul a:active { color: #FF0000; font-weight: 700; text-decoration: underline; }
#main_dd ul a:hover { color: #ffffff; font-weight: 700; text-decoration: underline; }
</style>
<script type="text/javascript">
sfHover = function() {
var sfEls = document.getElementById("main_dd").getElementsByTagName("li");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className=" sfhover";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
}
}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
</script>
</head>
<body>
<ul id="main_dd">
<li><a href="#">JOIN</a></li>
<li><a href="#">SERVICES</a>
<ul>
<li><a href="#">Login</a></li>
<li><a href="#">My Account Info</a></li>
<li><a href="#">Help</a></li>
<li><a href="#">Logout</a></li>
</ul>
</li>
</ul>
</body>
</html>

rocknbil

7:54 pm on Jun 18, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



This one's a little more complex and is an example of the "anywhere on page" menus. It's an image, positioned anywhere you want it, and when you click points on the image the menus appear. Initially it had over 100 "menus" and click points on the image. You'll need to come up with your own image and rewrite the image map, but I just tested with my images and it appears to be working.

Also note that every instance of ¦ must be replaced with the vertical pipe as a logical OR operator.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
<!-- doctype on one line -->
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Positioned list items Sample</title>
<style type="text/css">
#image_div { width: 455px; margin:auto; }
#illo { float: left; width: 221px; }
.hmenu {
margin: 0;
padding: 0;
font-size: 12px;
font-weight: 700;
width: 250px;
font-family: arial,helvetica,sans-serif;
color:#004080;
border-top: 2px solid #e9e9e9;
border-left: 2px solid #e9e9e9;
border-right: 2px solid #004080;
border-bottom: 2px solid #004080;
background-color: #EAEAFF;
position: absolute;
left: 500px;
top: 0;
display: none;
}
.hmenu li { list-style:none; margin:0; padding: 0; }
.hmenu a {
display: block;
padding: 6px 0 6px 0;
text-indent: 6px;
margin: 0;
width: 100%;
border-top: 1px solid #ffffff;
border-bottom: 1px solid #ffffff;
}
.hmenu li a:link { background-color: #EAEAFF; color: #004080; }
.hmenu li a:visited { color:#004080; }
.hmenu li a:active { color:#ff0000; }
.hmenu li a:hover {
color:#ffffff;
background-color: #004080;
}
</style>
<script type="text/javascript">
// Global variables and capture the mouse move event.
var IE = document.all?true:false;
if (!IE) document.captureEvents(Event.mouseClick);
document.onmousemove = trackCoords;
var x=y=divLeft=divRight=divTop=divBottom=0;
var divOpen=false;
// Track coordinates at all times and store in variables.
function trackCoords(e) {
if (!e) var e = window.event;
if (e.pageX ¦¦ e.pageY) {
x = e.pageX;
y = e.pageY;
}
else if (e.clientX ¦¦ e.clientY) {
x = e.clientX + document.body.scrollLeft
+ document.documentElement.scrollLeft;
y = e.clientY + document.body.scrollTop
+ document.documentElement.scrollTop;
}
hideMenus();
}
// Move hidden menu divs from left-hidden position and display.
function showMenu(id) {
var obj = document.getElementById(id);
var objLeft = x + 'px';
var objTop = y + 'px';
obj.style.display = 'block';
obj.style.left = objLeft;
obj.style.top = objTop;
divLeft = x;
divRight = parseInt(x+obj.offsetWidth);
divTop=y;
divBottom = parseInt(y+obj.offsetHeight);
divOpen=true;
return false;
}
//Prior to release of any getElementByClass method, assemble array of hidden menu divs by class.
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if (node == null) node = document;
if (tag == null) tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^¦\\s)"+searchClass+"(\\s¦$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}
//Hide menus ONLY if a div is "open" and the divs exceed the open box.
// Careful with this one or it will run all thetime and suck your memory into a black hole. :-)
function hideMenus() {
if ((divOpen==true) && ((divLeft>0) ¦¦ (divRight>0) ¦¦ (divTop>0) ¦¦ (divBottom>0))) {
divs = getElementsByClass('hmenu');
if ((y < divTop) ¦¦ (y > divBottom) ¦¦ (x < divLeft)¦¦ (x > divRight)) {
for (i=0;i<divs.length;i++) { resetDiv(divs[i]); }
divLeft=divRight=divTop=divBottom=0;
}
}
}
// Reset an open menu to the left 500 px, make it invisible again.
function resetDiv(d) {
d.style.left = '-500px';
d.style.top = 0;
d.style.display='none';
}
</script>
</head>
<body>
<div id="image_div">
<img id="illo" src="images/YOUR_IMAGE_HERE.jpg"
width="221" height="500" useMap="#illomap" alt="Click the image" border="0">
</div>
<ul class="hmenu" id="menu89_99">
<li><a href="#">Menu 89-99 item 1</a></li>
<li><a href="#">Menu 89-99 item 2</a></li>
<li><a href="#">Menu 89-99 item 3</a></li>
<li><a href="#">Menu 89-99 item 4</a></li>
<li><a href="#">Menu 89-99 item 5</a></li>
</ul>
<ul class="hmenu" id="menu100_101">
<li><a href="#">Menu 100-101 item 1</a></li>
<li><a href="#">Menu 100-101 item 2</a></li>
</ul>
<map name="illomap" id="illomap">
<area shape="poly" coords="95,8,107,3,117,3,125,9,123,12,113,15,105,15,97,13"
href="#" onClick="return showMenu('menu89_99');" alt="">
<area shape="poly" coords="130,20,126,23,118,23,130,31"
href="#" onClick="return showMenu('menu100_101');" alt="">
<area shape="rect" coords="0,0,0,0" alt="">
</map>
</body>
</html>

Edit: I just noticed I have some position: absolutes in there. What I meant with my initial statement was using absolute to position individual menu lists in a page layout with other absolute positioning. If you examine, absolute takes on a different meaning in these samples.

SuzyUK

9:35 pm on Jun 25, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Can someone explain to me the theory behind creating a javascript dropdown menu, but the menu is created from html/css markup.

Oh Yes.. as the "Churchill bulldog" says (possibly a UK thing?)

the theory is the same, if you understand the DOM for JS then you will understand the DOM for everything

then you take the Suckerfish Menu and realise that it is nothing more than a DOM manipulation ... it was JS applied (like a magic bullet) to an IE shortcoming.

I say "was" because I never used it and even today I don't see the need for it unless it's what you understand.

ALL effects need CSS of some sort whether you apply it by JS (or AJAX, whatever is the latest) doesn't matter the effect needs the same knowledge IMHO of course

AffiliateDreamer

5:28 pm on Jul 10, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Ok so it is correct to say it is just a play with display = 'block' and display = 'none' or is there more too it?

Are we playing with the z-index of the block to make it hover over all content and appear 3d'ish?

Is this basically how Facebook and flickr etc. do their menu system?

AffiliateDreamer

5:32 pm on Jul 10, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



I tried your more complicated example, and I placed Google's logo as the image.

Nothing seems to happen, even when I hover/click on the image?

[edited by: AffiliateDreamer at 5:33 pm (utc) on July 10, 2008]

SuzyUK

1:13 pm on Oct 1, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



There's a fundamental problem with CSS-only menus you've probably already guessed - when you mouse out of the visible menu item to mouse over the now-visible list, it causes the hover state of the base menu to cease, causing the drop down to disappear before you can get your mouse to it. This, and the case of graphic buttons, is where you need Javascript.

hmm playing catchup sorry for late reply .. but r'n'b that's not a fundamental shortcoming at all! CSS has always had the fundamentals even though we weren't always able to use them, perhaps - You can easily make the "base" menu retain whatever style you like, even once you're on a child, via CSS (if you were under the impression you can't, then it's because of IE's CSS support rather CSS's shortcomings) - and as for graphic 'buttons' .. maybe you should take a look at look up CSS sprites please :) again JS is not necessary, though the latest ALA article combines the two techniques quite pleasantly!

The fact is, although we've tried (there is code on the CSS forum!), we haven't been able to say how it could or should be done is because the naysayers would bite our CSS heads off, saying CSS wasn't ready yet ;) and then come to JS for the "solution".. it's not true that CSS is not ready, more likely IE needs bit of JS as a form of encouragement to "help" it support the CSS that's been ready for ages!

You simply have to set your :hover onto the correct element, until IE7 it wasn't possible (without a behaviour/script) to set the hover on anything except an anchor.. but if you set hover onto a span or the containing element itself <li>, <ul> and use child selectors you can easily achieve these effects via CSS alone, so to say you NEED JS for this is somewhat misleading

..anyway you do not *need* JS, though you may well *want* it in order to apply an aesthetic/slow/fade transition or something like that? Somewhere you have to decide where you're happy with the degradation of your effects for your audience (hint: they might be ones who are not primarily concerned with a PC display)!

CSS can give the transition without script, and to many medias at that, JS can help it "look pretty" in medias that support it.

and for a simple sample for Buckworks (albeit in the wrong forum) try this:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>horizontal dropdown</title>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
<style type="text/css" media="screen">
body {font-family:Verdana, Arial;}
#nav, #nav ul {
padding: 0;
margin: 0;
list-style: none;
}

#nav li {
float: left;
width: 10em;
padding-bottom: 20px; /* create a hoverable gutter if you want a gap between the base and the drop */
}

#nav li li {padding: 0;}

#nav a {
display: block;
width: 100%;
text-decoration:none;
background: #eee;
color:#000;
line-height: 1.6;
border: 1px solid #000;
text-align: center;
}
#nav a:hover {
background: #ff0;
}

#nav li ul {
position: absolute;
left: -1000em
}

#nav li:hover ul, #nav li.sfhover ul {
width: 10em; /* keep the HasLayout trigger off the main UL rule for IE7 */
top: auto;
margin-top: 15px; /* as long as it's less than the "gutter" there should be no loss of the drop before your mouse reaches it */
left: auto;
}

/* to make the base retain the active style, when you're on a child menu
this one will not work in IE6 not because of the hover but because it doesn't support the child selector
*/
#nav :hover>a {
background: #ff0;
}

/* it can be achieved for IE6 without the nice simple child selector too but might get a bit longwinded depending on how many menus you have */
#nav .sfhover a {background: #ff0;}
#nav .sfhover li a {background: #eee;}

</style>
<!--[if lt IE 7]>
<script type="text/javascript"><!--//--><![CDATA[//><!--
sfHover = function() {
var sfEls = document.getElementById("nav").getElementsByTagName("LI");
for (var i=0; i<sfEls.length; i++) {
sfEls[i].onmouseover=function() {
this.className+=" sfhover";
}
sfEls[i].onmouseout=function() {
this.className=this.className.replace(new RegExp(" sfhover\\b"), "");
}
}
}
if (window.attachEvent) window.attachEvent("onload", sfHover);
//--><!]]>
</script>
<![endif]-->
</head>
<body>
<div id="header">
<ul id="nav">
<li><a href="/">Coffee</a>
<ul>
<li><a href="/">decaff</a></li>
<li><a href="/">half-caff</a></li>
<li><a href="/">the real stuff</a></li>
</ul>
</li>
<li><a href="/">Tea</a></li>
<li><a href="/">Soda</a>
<ul>
<li><a href="/">Fizzy</a></li>
<li><a href="/">Still</a></li>
</li>
</ul>
</div>
<hr style="clear: both;">
</body>
</html>

the SF hover script is in there to encourage IE6 and below to support :hover on the li. IE7 now works without it (with one minor hasLayout tweak) the same effect can be achieved using a whatever:hover behaviour file but the JS is not making the effect work!

SuzyUK

1:29 pm on Oct 1, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Are we playing with the z-index of the block to make it hover over all content and appear 3d'ish?

Yes display: block/none is the theoretical way to do it.. although absolute positioning on/off the page does seem to suit IE better, no you needn't play with the z-index unless you want the drop menus to all appear on top of each other the z-index toggle can be used to create a different effect such as as tabbed top box where the viewable tab and menu change on hover.

I too tried rocknbils more complex example and couldn;t get it to work, however this is a <map> and is different altogether it combines 2 x techniques.. again CSS sprites may offer a viable/accesible (and more easily calculated) alternative

SuzyUK

11:45 am on Oct 3, 2008 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



sample "imagemap" using a CSS Sprite kind of based on rocknbil's code.. I've made the words "web" and "com" the "hotspots" - the pale yellow is just so you can visualise which part of the hover needs to remain "live" these parts are likely where you would have the background image sprite slide up to show e.g. a different colored part of the image - you would simply allow some padding on the hover in order to make it stay "live" so your mouse can reach your drop menu.

I presume then that JS could be added to make the whole effect also remain persistent onclick as well if required, so that without the JS it would degrade to this

I've used the WebmasterWorld logo and obviously can't provide a sprited rollover effect without linking out, however this method does appear to provide more possibilities than a simple <map> version, but having never used image maps I can't say for sure.. all I know is this is a lot less code and without either JS or CSS still degrades to provide a properly marked up list with top level headers attached, instead of an image you can't click

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Positioned list items Sample</title>
<style type="text/css">
#imagemap {
width: 380px; /* image width 109px + menu width 251px + a bit for visual */
min-height: 56px;
margin: auto;
background: #0f0 url(http://showcase.netins.net/web/phdss/WebmasterWorldgfx/dlogo.png) no-repeat 0 0;
position: relative;
}

#imagemap ul, #imagemap li {margin: 0; padding: 0; list-style: none;}

ul.popmenu {
font: bold 12px/1.6 arial,helvetica,sans-serif;
width: 247px; /* 251px less 4px for borders */
color: #004080;
background: #eaeaff;
border-width: 2px;
border-style: solid;
borer-color: #e9e9e9 #004080 #004080 #e9e9e9;
position: absolute;
visibility: hidden;
}

li#hot1 {position: absolute; top: 25px; left: 65px; width: 40px; background: #ffc;}
li#hot1 span {display: none;}
li#hot1 #pop1 {right: -20px; top: -25px;}
li#hot1:hover {padding: 0 250px 20px 0;}
li#hot1:hover .popmenu {visibility: visible;}

li#hot2 {position: absolute; top: 3px; left: 0px; width: 40px; background: #ffc;}
li#hot2 span {display: none;}
li#hot2 #pop2 {right: -85px; top: -3px;}
li#hot2:hover {padding: 0 250px 20px 0;}
li#hot2:hover .popmenu {visibility: visible;}

ul.popmenu a {
display: block;
padding: 6px 0;
text-indent: 6px;
width: 100%;
border-top: 1px solid #fff;
border-bottom: 1px solid #fff;
}

.popmenu li a:link { background-color: #EAEAFF; color: #004080; }
.popmenu li a:visited {color:#004080;}
.popmenu li a:hover {color:#ffffff; background: #004080;}
.popmenu li a:active {color:#ff0000; }

</style>
</head>
<body>
<div id="imagemap">
<ul class="hotspot">
<li id="hot1"><a href="#pop1"><span>Hotspot 1</span>.com</a>
<ul class="popmenu" id="pop1">
<li><a href="#">Menu 89-99 item 1</a></li>
<li><a href="#">Menu 89-99 item 2</a></li>
<li><a href="#">Menu 89-99 item 3</a></li>
</ul>
</li>
<li id="hot2"><a href="#pop2"><span>Hotspot 2</span>Web</a>
<ul class="popmenu" id="pop2">
<li><a href="#">Menu 100-101 item 1</a></li>
<li><a href="#">Menu 100-101 item 2</a></li>
</ul>
</li>
</ul>
</body>
</html>

and yes this would still need a ":hover helper" script for IE6 and below