-->
Bookmark and Share

Revenge of the Menu Bar

See the demo page for the finished version of the code.

Fixing the IE SELECT Overlap Problem

Browsers commonly have problems displaying absolutely positioned elements when they overlap special content on a web page, such as a Java applet or a plug-in. This is covered in more detail in the CSS Positioning article.

IE 6.0 Screenshot

IE in particular, has a problem with the SELECT form element. This can be seen in the screen shot at right where the SELECT box appears on top of the menus.

As forms are pretty common and there are many IE users (unfortunately), the problem should be addressed if the script is to useful.

The IFRAME Solution

One solution is to add an absolutely positioned IFRAME to the page. Unlike other positioned elements in IE, a positioned IFRAME will display properly when overlapping a SELECT element. That is, the SELECT element will not show through. Likewise, you can position any other element above the IFRAME and it will appear as expected.

The trick then, is to add an IFRAME to the page for every menu DIV, give it the same dimensions and position on the page as the menu and show or hide it in concert with the menu.

Adding an IFRAME to the Page

To do this, the following code is added to the menuInit() function.

// Fix the IE display problem (SELECT elements and other windowed controls
// overlaying the menu) by adding an IFRAME under the menu.

if (browser.isIE) {
  var iframeEl = document.createElement("IFRAME");
  iframeEl.frameBorder = 0;
  iframeEl.src = "javascript:false;";
  iframeEl.style.display = "none";
  iframeEl.style.position = "absolute";
  iframeEl.style.filter = "progid:DXImageTransform.Microsoft.Alpha(style=0,opacity=0)";
  menu.iframeEl = menu.parentNode.insertBefore(iframeEl, menu);
}

An IFRAME element is created and inserted into the page just before the menu DIV element. Style properties are set to make it absolutely positioned and hidden, just like the menu DIV.

Each menu gets its own IFRAME. A reference to that IFRAME is stored as a property of the menu's DIV element. This makes it easy to find the IFRAME associated with any given menu.

Using the IFRAME

Now we just need display or hide the IFRAME whenever its menu is shown. First, in the depressButton() function, we add the following code to handle the IFRAME when its menu is displayed.

// For IE; size, position and show the menu's IFRAME as well.

if (button.menu.iframeEl != null)
{
  button.menu.iframeEl.style.left = button.menu.style.left;
  button.menu.iframeEl.style.top  = button.menu.style.top;
  button.menu.iframeEl.style.width  = button.menu.offsetWidth + "px";
  button.menu.iframeEl.style.height = button.menu.offsetHeight + "px";
  button.menu.iframeEl.style.display = "";
}

It simply sets the position, width and height of the IFRAME element to match that of the menu DIV element and make it visible.

Similar code is used the menuItemMouseover() function where sub menus are displayed.

// For IE; size, position and show the menu's IFRAME as well.

if (item.subMenu.iframeEl != null)
{
  item.subMenu.iframeEl.style.left    = item.subMenu.style.left;
  item.subMenu.iframeEl.style.top     = item.subMenu.style.top;
  item.subMenu.iframeEl.style.width   = item.subMenu.offsetWidth + "px";
  item.subMenu.iframeEl.style.height  = item.subMenu.offsetHeight + "px";
  item.subMenu.iframeEl.style.display = "";
}

In resetButton(), where the menu is made hidden, we add this code to hide the IFRAME also.

    // For IE, hide menu's IFRAME as well.

    if (button.menu.iframeEl != null)
      button.menu.iframeEl.style.display = "none";

And again, in the closeSubMenu() function where sub menus are made hidden, we add code to hide the IFRAME as well.

// For IE, hide the sub menu's IFRAME as well.

if (menu.activeItem.subMenu.iframeEl != null)
  menu.activeItem.subMenu.iframeEl.style.display = "none";

Conclusion

That's it. The full source code can be found in the demo along with a sample bar and menus.

Hopefully this example has demonstrated the power and flexibility available using standard CSS, DOM and JavaScript. Obviously, there are still some compatibility issues with browsers that don't fully support these standards, but many of these can be worked around fairly easily, as shown here.

Two additional demos are provided. One shows how multiple menu bars can be used on a page. The other contains some script modifications which makes the buttons, menus and sub menus activate and deactivate on mouseovers and mouseouts instead of by clicking. You can check the comments in the source code of this demo to identify the changes made.