Email Me    Follow on Twitter    Download My CV

jQuery Horizontal Nav Fix

Lately a lot of websites have started using Horizontal navigation (like in this site), where the main navigation items of the site are aligned on the top (before the header, inside it or right underneath it) from left to right or center aligned.

Since the navigation is Horizontal and for aesthetic purposes we would usually try to make the navigation items fit the whole width of the page. Although in some cases (like in this site) we will opt for a more relaxed approach – which in this site case I decided to just align all items to the left and leave an empty space on the right hand side.

A third approach would be to align all items to the center of the page leaving the extra space in the right and left hand corners making a more symmetrical shape.

For the first approach (of fitting the navigation items exactly to the width of the page) the common solution was to generate the whole navigation as a set of images, which would have promised us an exact fit – however “flexibility wise” it meant setting the navigation items. So, if you ever wanted to change an item in the navigation, add a new one or remove an exiting one – this task would have become complex since you would have had to go back to your Image and re-create the navigation items again to fit.

Although you could have created the same navigation from text (as oppose to images) and used set CSS to align all items to fit – the problem you would have encountered would have been with the different operating systems, as MAC/OS and Linux render fonts a bit differently then Windows which causes the text on your navigation items to change it’s width a bit between operating systems and a navigation that would have fit perfectly on Internet Explorer might break on Safari (under MAC).

In this article, I will try to give a jQuery solution to this problem – and make a Horizontal navigation made from only text that fits it’s own items to the width of the page.

Let’s get down to code

The HTML of our navigation would look something like this:

<!-- We use a wrapper Nav div with UL, LI, A structure for the navigation items  -->
<div id="nav">
<ul>
	<li><a href="'#">Nav item 1</a></li>
	<li><a href="'#">Nav item 2</a></li>
	<li><a href="'#">Nav item 3</a></li>
</ul>
</div>

Your CSS should have something like the below snippet:

/*
The style just removes the bullet points from the LI elements and floats them to the left
*/
#nav ul li{
   list-style:none;
   flaot:left;
}
#nav ul li a{
   padding:10px;
   display:block;
}

Make sure your page has jQuery capabilities and include the JavaScript snippet below (either as a separate file or within the same page)

//This is where the magic happenes
jQuery(document).ready(function(){
    //sort nav to fit - in this case to 980px
    //you can change the figure below to the width of your navigation
    fixNav(980);
});

//this function loops through our nav items to determine it's width
function getNavWidth(){
    var navWidth = 0;
    //loops through each individual LI to figure out its DOM width and sums it all up
    jQuery('#nav ul > li').each(function(){
        navWidth = navWidth + jQuery(this).width() - 0;
    });
    return navWidth;
}

//main function call
function fixNav(navWidth){
    var navItem = -1;
    //while navigation is smaller then the required width
    //loop and make it smaller
    while(getNavWidth()<=navWidth){
        navItem++;
        if(navItem > jQuery('#nav ul > li').size() - 1) navItem = 0;
        var paddingleft = jQuery('#nav > ul > li:eq(' + navItem + ') a').css('paddingLeft').replace("px","");
        paddingleft = paddingleft - 0 + 1;
        //change padding on individual nav items as we loop through them to align navigation
        jQuery('#nav > ul > li:eq(' + navItem + ') a').css('paddingLeft',paddingleft + 'px');
        jQuery('#nav > ul > li:eq(' + navItem + ') a').css('paddingRight',paddingleft + 'px');
    }
    //while navigation is bigger then required width will reduce it's size
    while(getNavWidth()>navWidth){
        navItem++;
        if(navItem > jQuery('#nav ul > li').size() - 1) navItem = 0;
        var paddingleft = jQuery('#nav > ul > li:eq(' + navItem + ') a').css('paddingLeft').replace("px","");
        paddingleft = paddingleft - 1;
        jQuery('#nav > ul > li:eq(' + navItem + ') a').css('paddingLeft',paddingleft + 'px');
        jQuery('#nav > ul > li:eq(' + navItem + ') a').css('paddingRight',paddingleft + 'px');
    }
}

Comments

Got something to say? Leave a comment

Current ye@r *