http://nettuts.s3.amazonaws.com/386_navigation/200x200.png

A Different Top Navigation

When designing a new site, web designers usually face the age-old question: vertical or horizontal navigation? There are pros and cons to both solutions. One example being horizontal navigation limits the number of links you can have due to a limited page width. This is usually solved by including a drop down system. However, if you are attempting to make your particular site stand out, you might consider thinking outside the "norm".

In this tutorial, we will be doing precisely that. We will use jQuery to create a different multi-layered horizontal navigation system that is still intuitive enough for anyone to use for the first time.


To Learn:

At the end of this tutorial, we want to learn the following:

  • How to create cross-browser rounded pure CSS corners
  • Use jQuery to animate a top slider
  • Use jQuery to control the appearance of children unordered lists when the parent list item is hovered over.
  • Use jQuery to create a dynamic close capability

Objective:

At the end of this tutorial, we want to create a horizontal navigation system that does not use the typical drop down system.

Desired Effect

Page

Normal State – Click to View Full Size

Page

Expanded State – Click to View Full Size

Functionality

Let’s start by mapping out what we need to do in order to fufill out objective:

Expansion

  1. Wait for the user to hover over one of the main links
  2. Show the close X
  3. Make sure no main links have the active class (the class that will make their background match the sub link’s background)
  4. Add the active class to the main link that is hovered over
  5. Animate the height of the top bar to 40px
  6. Make sure no sub links are showing by hiding all sub links
  7. Show the sub-links of the main link that is being hovered over

Contraction

  1. Wait for the close X to be clicked
  2. Hide all sub links
  3. Remove the active class from all main links
  4. Animate the height of the sub link bar back to 10px
  5. Hide the close X

The HTML

There are already many great tutorials on this site for learning the basics of HTML & CSS, so for this tutorial I will assume you already know the basics. I’ll skip going into detail for this part:

For the actual page content, we will just use an image of the content to bypass the loss of quality that goes along with web text. This makes the HTML pretty simple:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>A Different Top Nav</title>
</head>
<body>
<div id="sub-link-bar"> </div>
<!-- End sub-link-bar -->
<div id="wrap">
  <div id="main-handle">
    <div class="roundfg">
      <ul id="main-nav">
        <li><a class="main-link" href="http://net.tutsplus.com/">Home</a>
        	<ul class="sub-links">
            	<li><a class="main-link" href="http://net.tutsplus.com/">Home</a></li>
            </ul>
        </li>
        <li><a class="main-link" href="http://net.tutsplus.com/category/tutorials/">Tutorials</a>
          <ul class="sub-links">
            <li><a href="http://net.tutsplus.com/category/tutorials/design-tutorials/" title="View all posts filed under Design">Design</a> </li>
            <li><a href="http://net.tutsplus.com/category/tutorials/html-css-techniques/" title="View all posts filed under HTML & CSS">HTML & CSS</a> </li>
            <li><a href="http://net.tutsplus.com/category/tutorials/other/" title="View all posts filed under Other">Other</a> </li>
            <li><a href="http://net.tutsplus.com/category/tutorials/php/" title="View all posts filed under PHP">PHP</a> </li>
            <li><a href="http://net.tutsplus.com/category/tutorials/ruby/" title="View all posts filed under Ruby">Ruby</a> </li>
            <li><a href="http://net.tutsplus.com/category/tutorials/site-builds/" title="View all posts filed under Site Builds">Site Builds</a> </li>
            <li><a href="http://net.tutsplus.com/category/tutorials/tools-and-tips/" title="View all posts filed under Tools & Tips">Tools & Tips</a> </li>
            <li class="cat-item cat-item-35"><a href="http://net.tutsplus.com/category/tutorials/wordpress/" title="View all posts filed under WordPress">WordPress</a> </li>
          </ul>
        </li>
        <li><a class="main-link" href="http://net.tutsplus.com/category/articles/">Articles</a>
          <ul class="sub-links">
            <li ><a href="http://net.tutsplus.com/category/articles/general/" title="View all posts filed under General">General</a> </li>
            <li><a href="http://net.tutsplus.com/category/articles/interviews/" title="View all posts filed under Interviews">Interviews</a> </li>
            <li><a href="http://net.tutsplus.com/category/articles/news/" title="View all posts filed under News">News</a> </li>
            <li><a href="http://net.tutsplus.com/category/articles/web-roundups/" title="View all posts filed under Web Roundups">Web Roundups</a> </li>
          </ul>
        </li>
        <li><a class="main-link" href="http://net.tutsplus.com/category/freebies/">Freebies</a>
          <ul class="sub-links">
            <li><a href="http://net.tutsplus.com/category/freebies/books/" title="View all posts filed under Books">Books</a> </li>
            <li><a href="http://net.tutsplus.com/category/freebies/icons-freebies/" title="View all posts filed under Icons">Icons</a> </li>
            <li><a href="http://net.tutsplus.com/category/freebies/lightboxes/" title="View all posts filed under Lightboxes">Lightboxes</a> </li>
            <li><a href="http://net.tutsplus.com/category/freebies/others/" title="View all posts filed under Others">Others</a> </li>
            <li><a href="http://net.tutsplus.com/category/freebies/plugins/" title="View all posts filed under Plugins">Plugins</a> </li>
            <li><a href="http://net.tutsplus.com/category/freebies/themes/" title="View all posts filed under Themes">Themes</a> </li>
            <li><a href="http://net.tutsplus.com/category/freebies/tooltips/" title="View all posts filed under Tooltips">Tooltips</a> </li>
          </ul>
        </li>
        <li><a class="main-link" href="http://net.tutsplus.com/category/videos/">Videos</a>
        	<ul class="sub-links">
            <li><a href="http://net.tutsplus.com/category/videos/screencasts/" title="Screencasts">Screencasts</a> </li>
         	</ul>
        </li>
        <li><a class="main-link" href="http://net.tutsplus.com/about">About</a>
        	<ul class="sub-links">
            	<li><a href="http://net.tutsplus.com/about/" title="About">About</a></li>
                <li><a href="http://tutsplus.com/join/" title="Join Plus">Join Plus</a></li>
                <li><a href="http://net.tutsplus.com/about/rss-feeds/" title="RSS Feeds">RSS Feeds</a></li>
                <li><a href="http://net.tutsplus.com/about/submissions/" title="Submit a Freebie">Submit a Freebie</a></li>
                <li><a href="http://net.tutsplus.com/about/terms/" title="Terms">Terms</a></li>
                <li><a href="http://net.tutsplus.com/about/write-a-tutorial/" title="Write a Tutorial">Write a Tutorial</a></li>
            </ul>
        </li>
         <li><a class="close" title="Click to Collapse" href="#">X</a></li>
      </ul>
    </div>
    <!-- End roundfg -->
    <b class="round"> <b class="round5"></b> <b class="round4"></b> <b class="round3"></b> <b class="round2"><b></b></b> <b class="round1"><b></b></b></b> </div>
  <!-- End main-handle-->
 </div>
<!-- End wrap -->
</body>
</html>
 

The CSS

The CSS is pretty simple too. Since this tutorial does not focus on HTML or CSS, if you have a specific question about it, you can drop me a line in the comments below.

html, body {
	background: #2d2620;
	text-align: center;
	margin: 0px;
	height: 100%;
	width: 100%;
}
#wrap {
	margin-left: auto;
	margin-right: auto;
	width: 900px;
	position: relative;
	background: url(body.png) center no-repeat;
	min-height: 600px;
}
#body-image {
	margin-top: 60px;
}
#main-nav {
	margin: 0px 0px 0px 2px;
	text-align: left;
	min-height: 25px;
	padding-top: 10px;
	padding-left: 0px;
}
#main-handle {
	width: 605px;
	float: right;
	margin-top: -1px;
}
#main-nav li {
	display: inline;
	list-style: none;
}
#main-nav li a {
	margin-right: 5px;
	font-size: 15px;
	text-decoration: none;
	color: #f2f2f2;
	font-family: Arial, Helvetica, sans-serif;
	text-transform: uppercase;
	font-weight: bold;
	padding: 10px;
	outline: 0;
	position: relative;
	top: -2px;
}
#main-nav li a:hover, #main-nav li a.active {
	background: #514539;
}
#sub-link-bar {
	background: #514539;
	min-height: 10px;
	border-bottom: #645546 1px solid;
}
.sub-links {
	display: none;
	position: absolute;
	width: 100%;
	top: -30px;
	text-align: left;
	left: 0px;
}
#main-nav li .sub-links li a:hover{
	background: #2d2620;
}
#main-nav li a.close{
	display: none;
	position: absolute;
}
#main-nav li a.close:hover{
	background: #900;
}

Rounded Corners

For this example, we’d also like to make the bottom corners rounded. There are many different solutions to this dilema, including using images, javascript, CSS or ususally a combination of the aforementioned. For this example, I’d like to achieve the corners using only CSS. Although CSS3 offers us an easy solution, it is still not cross browser compatible. So for this example, we are going to use an online service called Spiffy Corners. Spiffy Corners generates all the code for us. It’s pretty cool. We input the radius of the corners, the desired class name, and the background, and foreground color-it does the rest.

Page

Here’s the code it spitted out for us:

<style type="text/css">
.round{display:block}
.round *{
  display:block;
  height:1px;
  overflow:hidden;
  font-size:.01em;
  background:#645546}
.round1{
  margin-left:3px;
  margin-right:3px;
  padding-left:1px;
  padding-right:1px;
  border-left:1px solid #443a30;
  border-right:1px solid #443a30;
  background:#56493c}
.round2{
  margin-left:1px;
  margin-right:1px;
  padding-right:1px;
  padding-left:1px;
  border-left:1px solid #322a23;
  border-right:1px solid #322a23;
  background:#594c3e}
.round3{
  margin-left:1px;
  margin-right:1px;
  border-left:1px solid #594c3e;
  border-right:1px solid #594c3e;}
.round4{
  border-left:1px solid #443a30;
  border-right:1px solid #443a30}
.round5{
  border-left:1px solid #56493c;
  border-right:1px solid #56493c}
.roundfg{
  background:#645546}
</style>
Get the Code: HTML
<div>
  <b class="round">
  <b class="round1"><b></b></b>
  <b class="round2"><b></b></b>
  <b class="round3"></b>
  <b class="round4"></b>
  <b class="round5"></b></b>

  <div class="roundfg">
    <!-- content goes here -->
  </div>

  <b class="round">
  <b class="round5"></b>
  <b class="round4"></b>
  <b class="round3"></b>
  <b class="round2"><b></b></b>
  <b class="round1"><b></b></b></b>
</div>

Script Time

Let’s Go Over the Functionality Again:

  • Expansion

    1. Wait for the user to hover over one of the main links
    2. Show the close X
    3. Make sure no main links have the active class (the class that will make their background match the sub link’s background)
    4. Add the active class to the main link that is hovered over
    5. Animate the height of the top bar to 40px
    6. Make sure no sub links are showing by hiding all sub links
    7. Show the sub-links of the main link that is being hovered over

    Contraction

    1. Wait for the close X to be clicked
    2. Hide all sub links
    3. Remove the active class from all main links
    4. Animate the height of the sub link bar back to 10px
    5. Hide the close X

How We Are Going to Accomplish These Things

Add the Listener:

We put the handle on hover listener inside the on DOM reading function:

$(document).ready(function(){
	$("#main-nav li a.main-link").hover(function(){

	});	

});

Show the Close X

To show the X, we will use the fadeIn() function:

$("#main-nav li a.close").fadeIn();

Make sure no main links have the active class

To do this, we will remove the .active class from all main links

$("#main-nav li a.main-link").removeClass("active");
	

Add the active class to the element being hovered on

By using the “this” selector we can select the current element we are talking about. Since we are inside a hovering listener, it will add the class to the specific element that is being hovered on.

$(this).addClass("active");

Animate the height of the top bar to 40px

We will use the animate() function for this.

$("#sub-link-bar").animate({
			height: "40px"
		});
	

Make sure no sub-links are showing

To do this, we will use the same technique we used to remove the active class from all elements. Only this time, we will hide all sub-link lists.

$(".sub-links").hide();

Show the correct set of sub-links

To do this, we will select the sibling element of the hovered element and show the sibling list.

$(this).siblings(".sub-links").fadeIn();

Contraction

Now let’s add the ability to close the bar again. For this example, I’ve decided to include an X that will collapse the bar. For your example however, you could choose any method you think is the most intuitive and functional.

Wait for the X to be clicked

To do this, we will set an event listener that waits for the X to be clicked and then does something.

$("#main-nav li a.close").click(function(){

	});

Remove the active class from all main links

The first thing we want to do after the X is clicked is remove the active class from any main link, because when the menu is collapsing, nothing should be selected.

$("#main-nav li a.main-link").removeClass("active");

Hide all sub-links

Now that the bar is about to collapse, we need to hide all of the sub-links.

		$(".sub-links").fadeOut();;

Animate the Top bar back to 10px

Now we need to minimize the bar back to 10px

		$("#sub-link-bar").animate({			height: "10px"					   		});

Hide the X again

Now that the panel is collapsed, the user should not see an option to close the bar anymore. So we need to hide it again.

		$("#main-nav li a.close").fadeOut();

The Whole Script

Now that we’ve gone over the script in detail, let’s take a look at the whole thing:

$(document).ready(function(){
	$("#main-nav li a.main-link").hover(function(){
		$("#main-nav li a.close").fadeIn();
		$("#main-nav li a.main-link").removeClass("active");
		$(this).addClass("active");
		$("#sub-link-bar").animate({
			height: "40px"
		});
		$(".sub-links").hide();
		$(this).siblings(".sub-links").fadeIn();
	});
	$("#main-nav li a.close").click(function(){
		$("#main-nav li a.main-link").removeClass("active");
		$(".sub-links").fadeOut();
		$("#sub-link-bar").animate({
			height: "10px"
		});
		$("#main-nav li a.close").fadeOut();
	});
});

We’re Done


Congratulations! You have created a horizontal navigation system that will stand out on your site as different! I hope you have enjoyed the tutorial and found it useful in learning more about how to use jQuery for practical applications. If you have any questions or comments be sure to leave them in the comments below! I’d love to hear from you!


Add Comment

Discussion 106 Comments

Comment Page 2 of 2 1 2
  1. I love menu tips. Nothing makes or breaks a site like the menu.

  2. Patrick says:

    Clicking the ‘Desired effect’ images to see the full size version results in a 404 error.

  3. Perseco says:

    The following errors show up in Firefox 3.5.1′s error console when viewing the demo:

    Blocking cross site Javascript served from http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js with wrong mimetype text/x-c and included by http://nettuts.s3.amazonaws.com/386_navigation/top-nav-demo/index.html

    Error: $ is not defined
    Source File: http://nettuts.s3.amazonaws.com/386_navigation/top-nav-demo/index.html
    Line: 129

    • Connor Zwick says:

      Hi Perseco,

      From the error you copied over, it seems that your specific browser settings blocked the jQuery because it was from another site. Thus since jQuery was not loaded, all of the $ signs to begin jQuery functions went unrecognized because jQuery was never loaded.

  4. Brian says:

    Absolutely love it, thanks so much for this post.

    I think I will use this for a project in the future.

  5. Rohan says:

    I like the *effect* very much, but the thing is, I’m not so sure where it can be used. I woudn’t like having to browse a website with that sort of navigation.

  6. benoa says:

    I’m not fan of this. I would have put the sliding part down the main bar, that’d have been more ergonomic.

  7. chris says:

    You should use hoverIntent because now when you hover an item and try to go to a submenu item it’s easy to close the menu again… Just to make sure that the user is actually hover:ing over that item and not just passing by. :)

  8. Jonny says:

    It doesn’t like Firefox 3.5.1.

  9. nate says:

    Could you use image replacement for the buttons?
    And could you make a vertical menu like this-it seems like people are only making horizontal menus in this style these days.

  10. 阿呆 says:

    Cannot work fine in IE6!!

  11. sssss869 says:

    sometimes one sublink shows over another sublink, what to do? I want to use this navigation in my next project

  12. Sam Logan says:

    Very creative way to rework a navigation, looks incredible and works exceptionally well. Thank you for the tutorial.

  13. Joe says:

    Wow thats awsome!

    Im not going to use it personally but i think it looks amazing!

    NICE TUT!

  14. Dennis says:

    That is a amazing work and i use it well, but i want to change some thinks and do not how i can do this.

    I want to hide two #containers with the JS code, because i want to add a second div in the hidden div.

    Can anybody explain to me, in which way i have to change the JS code to get it?

    Thanks a lot and best regards
    Dennis

  15. Allegro says:

    For anyone else who may have an issue with a “handler is undefined” error being thrown. The issue is with the hover function in menu.js. The hover event takes 2 parameters and only one is defined. I just added a blank stub function to the event and the error went away.

    The new code is:

    $(document).ready(function(){
    $(“#main-nav li a.main-link”).hover(function(){
    $(“#main-nav li a.close”).fadeIn();
    $(“#main-nav li a.main-link”).removeClass(“active”);
    $(this).addClass(“active”);
    $(“#sub-link-bar”).animate({
    height: “40px”
    });
    $(“.sub-links”).hide();
    $(this).siblings(“.sub-links”).fadeIn();
    }, function(){});
    $(“#main-nav li a.close”).click(function(){
    $(“#main-nav li a.main-link”).removeClass(“active”);
    $(“.sub-links”).fadeOut();
    $(“#sub-link-bar”).animate({
    height: “10px”
    });
    $(“#main-nav li a.close”).fadeOut();
    });
    });

  16. foos says:

    Hey, thanks for this awesome menu.

    Is it possible to make the submenu with a downward movement instead of upwards?

    thanks

    • Mannie says:

      I to love this menu and looking for the desired effect for the sub menu to be below the main menu and push it up rather then the way it is now. has anyone accomplished this?

  17. Yes. It’s different!

  18. Drinker says:

    Nice, but… doesn’t work IE8 :(

  19. drtr says:

    hehehe…

  20. TessR says:

    I like it, however I do not want the user to click close to hide, it should hide itself when one roll out the menu. Any suggestions?

  21. Nick says:

    I would love to see an example where the sub-menu disappears when you ‘mouseout’ rather than clicking the X. Has anyone accomplished this?

  22. Bernardo says:

    Really really nice.

    But could I remove the option for closing, by eliminating the X?

  23. Rebekah says:

    Am I the only one having trouble with the menu titles stacking up on each other?

  24. Kelly says:

    Aloha,
    I have tried to use this menu on this website (http://www.valleyisleaquatics.com) and it works wonderfully when it is by itself. As soon as I put text under it or use PHP to call it in with the content page and footer page, it makes all the links not function in Firefox and Chrome, as well as the 1st link in IE8. I have tried backing up and starting over many times, and it still breaks all the page’s links. There must be something I am missing, a snipet, a work-around, a hack or something. I have been trying to fix this error for a couple of months to no avail, so any help here would be more than appreciated!=)
    Mahalo,
    Kelly

  25. Kelly says:

    I tried and tried to get this to work in Chrome and Firefox to no avail! Anytime there is a link below this, it blocks the link from being active. I have tried changing everything I can think of; rewriting from the beginning; putting it all on one page rather than rending via PHP, but nothing works. I am finally giving up on this menu, although I thought it was cool, if all the links below it don’t work, then it is not very useful.

  26. Greekie says:

    For those who were having issues with the submenu links stacking up on each other and messing everything up, hoverIntent was the way to go!

    Many thanks to Connor for this awesome menu! I had the stacking issue as well so I decided to tweak it a bit and added hoverIntent to the code.

    Here you go if anyone is interested

    $(document).ready(function() {
    $(“#main-nav li a.main-link”).hoverIntent(goUp, doNothing)
    });

    function goUp(){
    $(“#main-nav li a.close”).fadeIn();
    $(“#main-nav li a.main-link”).removeClass(“active”);
    $(this).addClass(“active”);
    $(“#sub-link-bar”).animate({
    height: “40px”
    });
    $(“.sub-links”).hide();
    $(this).siblings(“.sub-links”).fadeIn();
    };

    function doNothing() {};

    $(“#main-nav li a.close”).click(function() {
    $(“#main-nav li a.main-link”).removeClass(“active”);
    $(“.sub-links”).fadeOut();
    $(“#sub-link-bar”).animate({
    height: “10px”
    });
    $(“#main-nav li a.close”).fadeOut();
    });

    • Greekie says:

      It appears I didn’t realize the click function was left out so placing it in the goUp function allows the menu to work beautifully.

      Also, don’t forget to load the hoverIntent plugin right after jquery for this to work.

  27. Tom says:

    Good, but poor documentation. If I want the sub nav bar to appear BELOW themain links, how can one do that?

    Also, a fully worked example of this working with auto-close instead of [X] would be useful. Shame the thing is not easily configurable; my clients hate the sub-menu on top, so it can’t be used in a real life client website.

  28. du hoc my says:

    Dear,

    Your tutorial is so great but I am looking for the way to style wordpress 3.04 menu, not the simple html like your example. Can you teach me how to do this?

    Thank you,

  29. beckerist says:

    Question: If instead of showing the X, I want it to collapse on a timed instance, how do I do that? I’ve tried:

    $(document).ready(function(){
    $(“#main-nav li a.main-link”).hover(function(){
    $(“#main-nav li a.close”).fadeIn();
    $(“#main-nav li a.main-link”).removeClass(“active”);
    $(this).addClass(“active”);
    $(“#sub-link-bar”).animate({
    height: “40px”
    });
    $(“.sub-links”).hide();
    $(this).siblings(“.sub-links”).fadeIn();
    setTimeout(“timeMsg()”,5000);
    });
    function timeMsg() {
    $(“#main-nav li a.main-link”).removeClass(“active”);
    $(“.sub-links”).fadeOut();
    $(“#sub-link-bar”).animate({height: “10px”});
    $(“#main-nav li a.close”).fadeOut();
    }

    (for instance) along with multiple variations and it still doesn’t seem to work…what am I missing?

  30. Mike says:

    Question:

    How can i do to make lighted my sub-link when i’m in a subpage?
    It’s quite confusing when i’m surfing in sub-pages and you don’t know where u are without the sub-menu.

    Thank you very much!
    Great job!

  31. Abiodun says:

    Thanks so much for the menu, its excellent. However, I cant seem to get the code very well. Please, can you arrange the code in simple terms: which one should be in the head, body or a separate file. Please, reply. Thanks

  32. musicante says:

    Very nice menu.

    I am using it withing an html box in a master-frame but when adding a lightbox fancybox, the gallery would work… the static image opens in the browser.
    Is it maybe conflicting?

    Beginner here

    light box code

    $(document).ready(function()
    {
    $(“a[rel^='PhotoGallery1']“).fancybox({});
    });

    any help please?

    • musicante says:

      sorry I meant the gallery would NOT work…

      $(document).ready(function()
      {
      $(“a[rel^='PhotoGallery1']“).fancybox({});
      });

  33. Shirley says:

    Awesome! How can I make the sub menu stay up when it goes to its pages?

  34. Thanks for the source code. I was looking for it. I am using it on my blog..

  35. Quite nice, but I note there are still a few bugs, as pointed out by other comments…

  36. gary says:

    Great work guys keep it up… very very useful, master box is the way forward !

    Thanks Guys

  37. iYunes says:

    Hello guys,
    I have a small problem with the display on IE9, the menu keep flashes when mouse over, is there a solution for it?
    Thank you in advance

Comment Page 2 of 2 1 2

Add a Comment

To add a code snippet to your comment, please wrap your code like so: <pre name="code" class="html">YOUR CODE</pre>. You can replace the class name with "js," "css," "sql," or "php." If there are any "<" or ">" within your code, please search and replace them with: &lt; and &gt; respectively.