Member Sign In
Not a member?

A Wired.com user account lets you create, edit and comment on Webmonkey articles. You will also be able to contribute to the Wired How-To Wiki and comment on news stories at Wired.com.


It's fast and free.

Sign in with OpenID
Sign In
Webmonkey is a property of Wired Digital.
processing...
Join Webmonkey

Please send me occasional e-mail updates about new features and special offers from Wired/Webmonkey.
Yes No

Please send occasional e-mail offers from Wired/Webmonkey affiliated web sites and publications, and carefully selected companies.
Yes No

I understand and agree that registration on or use of this site constitutes agreement to Webmonkey's User Agreement and Privacy Policy.
Webmonkey is a property of Wired Digital.
processing...

Retrieve Sign In

Please enter your e-mail address or username below. Your username and password will be sent to the e-mail address you provided us.

or
Webmonkey is a property of Wired Digital.
processing...

Welcome to Webmonkey

A private profile page has been created for you.
As a member of Webmonkey, you can now:
  • edit articles
  • add to the code library
  • design and write a tutorial
  • comment on any Webmonkey article
Close
Webmonkey is a property of Wired Digital.

Sign In Information Sent

An e-mail has been sent to the e-mail address registered in this account.
If you cannot find it in your in-box, please check your bulk or junk folders.
Sign In
Webmonkey is a property of Wired Digital.

Multi browser hover menu without Javascript

/skill level/
/viewed/
0 Times

Contents

Introduction

The following article describes how to create a hover menu that will look the same in the most common browsers without making use of Javascript.

To make it work for Internet Explorer it makes use of the hover-behavior-technique developed by Peter Nederlof. http://www.xs4all.nl/~peterned/

What you'll need

In the following we will make use of the following files.

- 2 images
- 1 HTC file
- 1 HTML file
- 2 CSS files

Steps

To make it work we use the ":hover"-pseudo-class object. Firefox and Opera can handle it properly and with the help of the HTC file Internet Explorer 6 can handle it too. Internet Explorer 7 does not need it, but it doesn't hurt either.

HTC file:
- http://tutorial.darkmasters.de/hover_menu_without_js/hover.htc

 <attach event="ondocumentready" handler="parseStylesheets" />
 
 <script>
 /*
  *  Whatever:hover - V1.42.060206 - hover & active
  *  ------------------------------------------------------------
  *  (c) 2005 - Peter Nederlof
  *  Peterned - http://www.xs4all.nl/~peterned/
  *  License  - http://creativecommons.org/licenses/LGPL/2.1/
  *
  *  Whatever:hover is free software; you can redistribute it and/or
  *  modify it under the terms of the GNU Lesser General Public
  *  License as published by the Free Software Foundation; either
  *  version 2.1 of the License, or (at your option) any later version.
  *
  *  Whatever:hover is distributed in the hope that it will be useful,
  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  *  Lesser General Public License for more details.
  *
  *  Credits and thanks to:
  *  Arnoud Berendsen, Martin Reurings, Robert Hanson
  *
  *  howto: body { behavior:url("csshover.htc"); }
  *  ------------------------------------------------------------
  */
 
 var csshoverReg = /(^|\s)(([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active)/i,
 currentSheet, doc = window.document, hoverEvents = [], activators = 
 {
   onhover:{on:'onmouseover', off:'onmouseout'},
   onactive:{on:'onmousedown', off:'onmouseup'}
 }
 
 function parseStylesheets() 
 {
   if(!/MSIE (5|6|7|8)/.test(navigator.userAgent)) return;
   window.attachEvent('onunload', unhookHoverEvents);
   var sheets = doc.styleSheets, l = sheets.length;
   for(var i=0; i<l; i++) 
     parseStylesheet(sheets[i]);
 }
   
 function parseStylesheet(sheet) 
 {
   if(sheet.imports) 
   {
     try 
     {
       var imports = sheet.imports, l = imports.length;
       for(var i=0; i<l; i++) parseStylesheet(sheet.imports[i]);
     } catch(securityException){}
   }
   try 
   {
     var rules = (currentSheet = sheet).rules, l = rules.length;
     for(var j=0; j<l; j++) parseCSSRule(rules[j]);
   } catch(securityException){}
 }
 
 function parseCSSRule(rule) 
 {
   var select = rule.selectorText, style = rule.style.cssText;
   if(!csshoverReg.test(select) || !style) return;
   var pseudo = select.replace(/[^:]+:([a-z-]+).*/i, 'on$1');
   var newSelect = select.replace(/(\.([a-z0-9_-]+):[a-z]+)|(:[a-z]+)/gi, '.$2' + pseudo);
   var className = (/\.([a-z0-9_-]*on(hover|active))/i).exec(newSelect)[1];
   var affected = select.replace(/:(hover|active).*$/, );
   var elements = getElementsBySelect(affected);
   if(elements.length == 0) return;
   currentSheet.addRule(newSelect, style);
   for(var i=0; i<elements.length; i++)
     new HoverElement(elements[i], className, activators[pseudo]);
 }
 
 function HoverElement(node, className, events) 
 {
   if(!node.hovers) node.hovers = {};
   if(node.hovers[className]) return;
   node.hovers[className] = true;
   hookHoverEvent(node, events.on, function() { node.className += ' ' + className; });
   hookHoverEvent(node, events.off, function() { node.className = node.className.replace(new RegExp('\\s+'+className, 'g'),); });
 }
 
 function hookHoverEvent(node, type, handler) 
 {
   node.attachEvent(type, handler);
   hoverEvents[hoverEvents.length] = { node:node, type:type, handler:handler };
 }
 
 function unhookHoverEvents() 
 {
   for(var e,i=0; i<hoverEvents.length; i++) {
     e = hoverEvents[i]; 
     e.node.detachEvent(e.type, e.handler);
   }
 }
 
 function getElementsBySelect(rule) 
 {
   var parts, nodes = [doc];
   parts = rule.split(' ');
   for(var i=0; i<parts.length; i++) {
     nodes = getSelectedNodes(parts[i], nodes);
   }  return nodes;
 }
 
 function getSelectedNodes(select, elements) 
 {
   var result, node, nodes = [];
   var identify = (/\#([a-z0-9_-]+)/i).exec(select);
   if(identify) 
   {
     var element = doc.getElementById(identify[1]);
     return element? [element]:nodes;
   }
   
   var classname = (/\.([a-z0-9_-]+)/i).exec(select);
   var tagName = select.replace(/(\.|\#|\:)[a-z0-9_-]+/i, );
   var classReg = classname? new RegExp('\\b' + classname[1] + '\\b'):false;
   for(var i=0; i<elements.length; i++) 
   {
     result = tagName? elements[i].all.tags(tagName):elements[i].all; 
     for(var j=0; j<result.length; j++) 
     {
       node = result[j];
       if(classReg && !classReg.test(node.className)) continue;
       nodes[nodes.length] = node;
     }
   }  
   
   return nodes;
 }
 
 </script>

CSS files:
- http://tutorial.darkmasters.de/hover_menu_without_js/screen.css
- http://tutorial.darkmasters.de/hover_menu_without_js/screen_ie.css

screen.css

 * {
   margin:0;
   padding:0;
 }
 
 body {
   padding:2em;
   font-size:62.5%;
   font-family:verana,sans-serif;
 }
 
 h1 {
   font-size:250%;
   margin-bottom:0.7em;
 }
 #nav {
   zoom:1;
   padding-bottom:2em;
 }
 
 p {
   font-size:1.2em;
   line-height:1.7em;
   margin-bottom:1.5em;
   width:50em;
   margin-left:0.1em;
 }
 
 #nav a span {
   font-size:1.2em;
 }
 
 #nav ul {
   list-style-type:none;
 }
 #nav ul li ul {
   background:transparent url(ulback.gif) top left no-repeat;
 }
 
 #nav ul li {
   float:left;
   margin-right:0.1em;
   border:0.1em solid #ddd;
 }
 
 #nav a {
   padding:0.5em 1em;
   background:#eee;
   display:block;
   color:blue;
   text-decoration:none;
 }
 
 #nav a.arrow {
   padding-right:2em;
   background:#eee url(arrow.gif) center right no-repeat;
 }
 
 #nav a.arrow:hover,
 #nav a:hover {
   background-color:#f7f7f7;
   color:red;
 }
 
 #nav ul li ul {
   position:absolute;
   display:none;
   padding-top:0.2em;
   margin-left:-0.1em;
 }
 
 #nav ul li:hover ul {
   display:block;
 }
 
 #nav ul li:hover ul li ul {
   display:none;
 }
 
 #nav ul li ul li:hover ul {
   display:block;
 }
 
 #nav ul li ul li:hover ul li ul {
   display:none;
 }
 
 #nav ul li ul li ul li:hover ul {
   display:block;
 }
 
 #nav ul li ul li {
   float:none;
   margin:0;
   border:0.1em solid #ddd;
   margin-bottom:0.1em;
   width:15em;
 }
 
 #nav ul li ul li ul {
   margin-left:15em;
   margin-top:-2.8em;
   padding-left:0.2em;
   display:none;
 }    

screen_ie.css

 body {
   behavior:url("hover.htc");
 }
 #nav ul li ul li {
   margin-bottom:-2px;
 }
   
 #nav ul li ul li ul {
   margin-left:14.8em;
   margin-top:-2.8em;
   padding-left:0.2em;
   display:none;
 } 

Images:
- Media:Ulback.gif
- Media:Arrow.gif

ulback.gif This image has 300px width and 600px height. Its filled with white color and saved as GIF.

arrow.gif This image is very small. 11px width and 9px height. This will be shown if there is any submenu.

HTML file:
- http://tutorial.darkmasters.de/hover_menu_without_js/example.html

<html> <head>

 <title>Multi browser hover menu without Javascript</title>
 
 <link rel="stylesheet" type="text/css" media="screen" href="screen.css" />

 <!--[if IE]>
   <link rel="stylesheet" type="text/css" media="screen" href="screen_ie.css" />
 <![endif]-->
 

</head> <body>

 <h1>Multi browser hover menu without Javascript</h1>
 <div id="nav">
 
   <ul>
     <li><a href="#"><span>First point</span></a>
       <ul>
         <li><a href="#"><span>Sub Point1 adfasdf</span></a></li>
         <li><a href="#" class="arrow"><span>Sub Point2</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#"><span>link2</span></a></li>
           </ul>
         </li>
         <li><a href="#" class="arrow"><span>Sub Point3</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#" class="arrow"><span>link2</span></a>
               <ul>
                 <li><a href="#"><span>link1</span></a></li>
                 <li><a href="#"><span>link2</span></a></li>
                 <li><a href="#"><span>link3</span></a></li>
                 <li><a href="#"><span>link4</span></a></li>
                 <li><a href="#"><span>link5</span></a></li>
               </ul>
             </li>
             <li><a href="#"><span>link3</span></a></li>
             <li><a href="#"><span>link4</span></a></li>
             <li><a href="#"><span>link5</span></a></li>
           </ul>
         </li>
         <li><a href="#"><span>Sub Point4</span></a></li>
         <li><a href="#"><span>Sub Point5</span></a></li>
       </ul>
     </li>
     <li><a href="#"><span>Second point</span></a>
       <ul>
         <li><a href="#"><span>Sub Point1 adfasdf</span></a></li>
         <li><a href="#" class="arrow"><span>Sub Point2</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#"><span>link2</span></a></li>
           </ul>
         </li>
         <li><a href="#" class="arrow"><span>Sub Point3</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#" class="arrow"><span>link2</span></a>
               <ul>
                 <li><a href="#"><span>link1</span></a></li>
                 <li><a href="#"><span>link2</span></a></li>
                 <li><a href="#"><span>link3</span></a></li>
                 <li><a href="#"><span>link4</span></a></li>
                 <li><a href="#"><span>link5</span></a></li>
               </ul>
             </li>
             <li><a href="#"><span>link3</span></a></li>
             <li><a href="#"><span>link4</span></a></li>
             <li><a href="#"><span>link5</span></a></li>
           </ul>
         </li>
         <li><a href="#"><span>Sub Point4</span></a></li>
         <li><a href="#"><span>Sub Point5</span></a></li>
       </ul>
     </li>
     <li><a href="#"><span>Third point</span></a>
       <ul>
         <li><a href="#"><span>Sub Point1 adfasdf</span></a></li>
         <li><a href="#" class="arrow"><span>Sub Point2</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#"><span>link2</span></a></li>
           </ul>
         </li>
         <li><a href="#" class="arrow"><span>Sub Point3</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#" class="arrow"><span>link2</span></a>
               <ul>
                 <li><a href="#"><span>link1</span></a></li>
                 <li><a href="#"><span>link2</span></a></li>
                 <li><a href="#"><span>link3</span></a></li>
                 <li><a href="#"><span>link4</span></a></li>
                 <li><a href="#"><span>link5</span></a></li>
               </ul>
             </li>
             <li><a href="#"><span>link3</span></a></li>
             <li><a href="#"><span>link4</span></a></li>
             <li><a href="#"><span>link5</span></a></li>
           </ul>
         </li>
         <li><a href="#"><span>Sub Point4</span></a></li>
         <li><a href="#"><span>Sub Point5</span></a></li>
       </ul>
     </li>
     <li><a href="#"><span>Fourth point</span></a>
       <ul>
         <li><a href="#"><span>Sub Point1 adfasdf</span></a></li>
         <li><a href="#" class="arrow"><span>Sub Point2</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#"><span>link2</span></a></li>
           </ul>
         </li>
         <li><a href="#" class="arrow"><span>Sub Point3</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#" class="arrow"><span>link2</span></a>
               <ul>
                 <li><a href="#"><span>link1</span></a></li>
                 <li><a href="#"><span>link2</span></a></li>
                 <li><a href="#"><span>link3</span></a></li>
                 <li><a href="#"><span>link4</span></a></li>
                 <li><a href="#"><span>link5</span></a></li>
               </ul>
             </li>
             <li><a href="#"><span>link3</span></a></li>
             <li><a href="#"><span>link4</span></a></li>
             <li><a href="#"><span>link5</span></a></li>
           </ul>
         </li>
         <li><a href="#"><span>Sub Point4</span></a></li>
         <li><a href="#"><span>Sub Point5</span></a></li>
       </ul>
     </li>
     <li><a href="#"><span>Fifth point</span></a>
       <ul>
         <li><a href="#"><span>Sub Point1 adfasdf</span></a></li>
         <li><a href="#" class="arrow"><span>Sub Point2</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#"><span>link2</span></a></li>
           </ul>
         </li>
         <li><a href="#" class="arrow"><span>Sub Point3</span></a>
           <ul>
             <li><a href="#"><span>link1</span></a></li>
             <li><a href="#" class="arrow"><span>link2</span></a>
               <ul>
                 <li><a href="#"><span>link1</span></a></li>
                 <li><a href="#"><span>link2</span></a></li>
                 <li><a href="#"><span>link3</span></a></li>
                 <li><a href="#"><span>link4</span></a></li>
                 <li><a href="#"><span>link5</span></a></li>
               </ul>
             </li>
             <li><a href="#"><span>link3</span></a></li>
             <li><a href="#"><span>link4</span></a></li>
             <li><a href="#"><span>link5</span></a></li>
           </ul>
         </li>
         <li><a href="#"><span>Sub Point4</span></a></li>
         <li><a href="#"><span>Sub Point5</span></a></li>
       </ul>
     </li>
   </ul>
   
   <div style="clear:left;"></div>
 
 </div>
 
 <div>
 
     <p>Weit hinten, hinter den Wortbergen, fern der Länder Vokalien und 
       Konsonantien leben die Blindtexte. Abgeschieden wohnen Sie in Buchstabhausen 
       an der Küste des Semantik, eines großen Sprachozeans. Ein kleines 
       Bächlein namens Duden fließt durch ihren Ort und versorgt sie 
       mit den nötigen Regelialien. Es ist ein paradiesmatisches Land, in 
       dem einem gebratene Satzteile in den Mund fliegen. Nicht einmal von der 
       allmächtigen Interpunktion werden die Blindtexte beherrscht ein 
       geradezu unorthographisches Leben.</p>
     <p>Eines Tages aber beschloß eine kleine Zeile Blindtext, ihr Name 
       war Lorem Ipsum, hinaus zu gehen in die weite Grammatik. Der große 
       Oxmox riet ihr davon ab, da es dort wimmele von bösen Kommata, wilden 
       Fragezeichen und hinterhältigen Semikoli, doch das Blindtextchen 
       ließ sich nicht beirren. Es packte seine sieben Versalien, schob 
       sich sein Initial in den Gürtel und machte sich auf den Weg.</p>
     <p>Als es die ersten Hügel des Kursivgebirges erklommen hatte, warf 
       es einen letzten Blick zurück auf die Skyline seiner Heimatstadt 
       Buchstabhausen, die Headline von Alphabetdorf und die Subline seiner eigenen 
       Straße, der Zeilengasse. Wehmütig lief ihm eine rethorische 
       Frage über die Wange, dann setzte es seinen Weg fort.</p>
     <p>Unterwegs traf es eine Copy. Die Copy warnte das Blindtextchen, da, wo 
       sie herkäme wäre sie zigmal umgeschrieben worden und alles, 
       was von ihrem Ursprung noch übrig wäre, sei das Wort "und" und 
       das Blindtextchen solle umkehren und wieder in sein eigenes, sicheres 
       Land zurückkehren. </p>
     <p>Doch alles Gutzureden konnte es nicht überzeugen und so dauerte 
       es nicht lange, bis ihm ein paar heimtückische Werbetexter auflauerten, 
       es mit Longe und Parole betrunken machten und es dann in ihre Agentur 
       schleppten, wo sie es für ihre Projekte wieder und wieder mißbrauchten. 
       Und wenn es nicht umgeschrieben wurde, dann benutzen Sie es immernoch.</p>
 
 
 </div>

</body> </html>

Result:
http://tutorial.darkmasters.de/hover_menu_without_js/example.html

Suggested readings

http://msdn.microsoft.com/en-us/library/ms531018(VS.85).aspx
http://www.xs4all.nl/~peterned/

  • This page was last modified 06:58, 14 August 2008.
Edit this article
Reddit Digg
 
Subscribe now

Special Offer For Webmonkey Users

WIRED magazine:
The first word on how technology is changing our world.

Subscribe for just $10 a year