Back to Top

Sunday, October 05, 2008

Creating a horizontal menu with jQuery

I've looked around on the net for something similar, but I couldn't find it, so here is some quick code I've put together.

Requirements: create a two-level horizontal menu. The menu will be on a separate page on the top frame (yes, frames are so '90, but they can easily integrate multiple sites). Initially I was going for the "mouse over to activate" technique, however I've got a lot of feedback saying that it is too sensitive / "jumpy" that way.

The markup: as most other menus, I've used lists to codify the menu structure. The upper level is placed in a special menul with the id "top_level":

 <ul id="top_level">
  <li><a href="foo" target="_top">Foo</a></li>
  <li><a href="#bar">Bar</a></li>
  <li><a href="#bar2">Bar (more)</a></li>
 </ul>

As you can see, the links can be of two types: direct links to content and links to submenus. In this second case the anchor name must coincide with the id of the div, minus the hash (#) character. So for example for the link "#bar" we have a div with the id "bar".

The submenus are lists themselves, wrapped in divs with the appropriate ID's:

 <div id="bar">
  <ul>
   <li><a href="http://example.com" target="work_frame">Foo</a></li>
   <li><a href="http://example.com" target="work_frame">Foo</a></li>
   ...
  </ul>
 </div>

 <div id="bar2">
  <ul>
      <li><a href="http://example.com" target="work_frame">Bar</a></li>
      <li><a href="http://example.com" target="work_frame">Bar</a></li>
      ...
  </ul>
 </div>

And here is the JS code to make it all work:

$(function() {
 $('div').hide();
 
 var id_href = /^#(.*)/;
 $('#top_level a').click(function () {
  $('div').hide();
  $('#top_level a').css('background-color', '#DDD');    
  if (id_href.test($(this).attr('href'))) {
   $($(this).attr('href')).show();     
   $(this).css('background-color', '#BBB');     
   window.top.document.body.rows = '' + 
    ($('#top_level').height() + $($(this).attr('href')).height()) + ',*';     
   return false;
  } else
   window.top.document.body.rows = '' + $('#top_level').height() + ',*';
 });
});

How it works:

  • It hides all the divs (the code is written with the assumption that it is the only thing on the page
  • When a link is clicked in the upper list, first a test is done to see if it is a direct link or a link to a submenu.
  • The appropriate coloring is done and the frame height is adjusted.

With all this you also need a stylesheet. The most important things are: removing the spacing between the elements and the borders of the page and to place the list elements inline:

* {
 padding: 0;
 margin: 0;
 border: 0;
}
li { 
 display: inline; 
 padding-left: 1em; padding-right: 1em;
}
a {
 text-decoration: none;
 color: #000;
 font-weight: bold;
 font-family: Courier New, monospace;
 font-size: 1em;
 padding-left: 0.3em; padding-right: 0.3em;
}
a.help_link {
 padding-left: 0; padding-right: 0;
}
a:hover {
 font-weight: bold;
 background-color: #999;
 color: #000;
}
body {
 background-color: #DDD;
 paddign-bottom: 5em;
}
div {
 background-color: #BBB;
}

The final result looks something like this:

Click here to download the complete file (around 2k).

Update:

For further clarification I included a small visual explanation of which element affects the color of what:

  1. The text colors for all links (both the upper row and the lower row)
  2. The text color for all the links when hovered over them
  3. The same as the above for the background color
  4. The background color for the body. This can be seen most prominently on the upper bar
  5. Background color for the lower row
  6. Background color for not-selected upper row elements (this should be the same as the background color for the body)
  7. Background color for selected upper row elements (this should be identical with the background of the lower row elements)

Admittedly I could have omitted the two hardcoded colors from the javascript and get it dynamically from the CSS, but I was lazy :-). Hopefully this visual explanation helps.

7 comments:

  1. Anonymous1:28 PM

    Hi there, first of all hat off to you for this tutorial. I've been looking for this kind of tabbing feature using jquery. could you please tell me how to set an active backround or color of text for the submenu(s)? Am very new to jquery and its implementation. regards

    ReplyDelete
  2. If I'm understanding you correctly, you want to change the background of the active (selected) "tab". The JQuery code which is responsible for this is:

    $(this).css('background-color', '#BBB');

    Just change #BBB into any color you would like.

    Hope this helps.

    ReplyDelete
  3. Anonymous3:22 AM

    Hi there, I guess that if I follow the step you said above, it will also affect the 2nd level menu(s) when active? Regards

    ReplyDelete
  4. @Anonymous - I updated the post with a visual explanation. Hopefully this helps clarify the effect of the CSS / JS on the colors of the menu.

    ReplyDelete
  5. This is professional and perfect. Thank you very much.

    ReplyDelete
  6. excellent! would you be so kind as to post a tutorial as easy to follow as this but for the 3d rotating tag cloud? thanks!

    ReplyDelete
  7. @Prototype: there is already a tutorial located here: http://hype-free.blogspot.com/2009/03/blogger-tag-cloud.html. Let me know if I can help with any further clarifications.

    Best regards.

    ReplyDelete