Aug 19, 2008

jQuery Tabbed Navigation

It seems like more and more these days, JavaScript tabbed interfaces are being used. There are plenty of scripts out there, but I think it is important to be able to do things yourself. A lot of JavaScript “plugins” that you will find online will give you way more than you really need, and you may understand how to use it, but you will not really understand what it is really doing.

First, I thought I would walk through creating a tabbed navigation script with jQuery, and then modifying it so that it works without JavaScript.

If you want to skip ahead, take a look at the sample jQuery tabbed interface.

The Markup

I’m going to set this up using classes so that it is possible to use this multiple times on a page. There are two different pieces to the markup: the navigation and the actual content for the tabs.

The Navigation

<ul class="tabNav">
 <li class="current"><a href="#">Tab 1</a></li>
 <li><a href="#">Tab 2</a></li>
 <li><a href="#">Tab 3</a></li>
 <li><a href="#">Tab 4</a></li>
 <li><a href="#">Tab 5</a></li>
</ul> 

Pretty straightforward, just an un-ordered list. The JavaScript will accommodate any number of tabs. Notice that the first tab has a class of current. This will be the class to style to show the active tab.

The Tab Content

<div class="tabContainer">
 <div class="tab current">
  &hellip;Content for Tab 1&hellip;
 </div>
 <div class="tab">
  &hellip;Content for Tab 2&hellip;
 </div>
 <div class="tab">
  &hellip;Content for Tab 3&hellip;
 </div>
 <div class="tab">
  &hellip;Content for Tab 4&hellip;
 </div>
 <div class="tab">
  &hellip;Content for Tab 5&hellip;
 </div>
</div> 

Again, pretty straightforward: a container and a div for each of the tabs’ content. A couple of things to note: the first tab content also has a class of current, and the tabs’ content divs need to appear in the same order as the navigation.

Some Basic CSS

I’m not going to explain how I completely style my example, but I will highlight the necessary styles for the tabs to work.

To highlight the active tab, this is what you want to style:

ul.tabNav li.current a { &hellip; } 

In order to hide all of the tabs’ contents except for the active tab, these are the styles that are necessary:

div.tabContainer div.tab { display: none; }
div.tabContainer div.current { display: block; } 

The JavaScript

Ok, this is definitely the meat of the post. Since I wanted this to be as generic and simple as possible, I made heavy use of the parent and children selectors.

So to start, we want to add onclick events to the tabs:

$(document).ready(function(){
 $('ul.tabNav a').click(function() {
  &hellip;
  return false;        
 });
}); 

When each tab is clicked, we want to see which tab was clicked on so that we can show the appropriate content. So we count the previous number of siblings of the parent (the list item) and store it in the curChildIndex variable:

$(document).ready(function(){
 $('ul.tabNav a').click(function() {
  <strong>var curChildIndex = $(this).parent().prevAll().length + 1;</strong>
  &hellip;
  return false;        
 });
}); 

Next, we want to remove the class of current from the currently selected tab, and add the class of current to the tab we just clicked:

$(document).ready(function(){
 $('ul.tabNav a').click(function() {
  var curChildIndex = $(this).parent().prevAll().length + 1;
  <strong>$(this).parent().parent().children('.current').removeClass('current');
  $(this).parent().addClass('current');</strong>
  &hellip;
  return false;        
 });
}); 

The final step is to hide the tab content that is currently showing and to show the tab content that matches the tab that was just clicked on. This is where we will make use of the curChildIndex variable and the nth Child Selector:

$(document).ready(function(){
 $('ul.tabNav a').click(function() {
  var curChildIndex = $(this).parent().prevAll().length + 1;
  $(this).parent().parent().children('.current').removeClass('current');
  $(this).parent().addClass('current');
  <strong>$(this).parent().parent().next('.tabContainer').children('.current').slideUp('fast',function() {
   $(this).removeClass('current');
   $(this).parent().children('div:nth-child('+curChildIndex+')').slideDown('normal',function() {
    $(this).addClass('current');
   });
  });</strong>
  return false;        
 });
}); 

The previous snippet of the code is traversing from the clicked tab ,(this), to the current content that has a class of current, sliding that up, and removing the class of current. Once that is complete, we are selecting the tab content that matches the tab clicked, sliding it down, and adding the class of current.

Take a look at the sample jQuery tabbed interface to see it in action.

Making it Work for Non-JavaScript Users

Now, that works great, but what about people who don’t have JavaScript enabled? Sure it’s a very small number, but we still want to account for those people.

Most other JavaScript tab scripts use JavaScript to hide the non-active tab content sections or to write in the tabbed navigation, but then you get that flash of changing content. My idea is to use CSS to hide the non active tab content (which I discussed earlier) and pass a parameter into the URL to select which tab to show.

The Code

Below is the new code for the tab navigation:

<ul class="tabNav">
 <li<?php if(!isset($_GET['tab'])) echo ' class="current"';?>><a href="">Tab 1</a></li>
 <li<?php if(isset($_GET['tab']) && $_GET['tab'] == 2) echo ' class="current"';?>><a href="?tab=2">Tab 2</a></li>
 <li<?php if(isset($_GET['tab']) && $_GET['tab'] == 3) echo ' class="current"';?>><a href="?tab=3">Tab 3</a></li>
 <li<?php if(isset($_GET['tab']) && $_GET['tab'] == 4) echo ' class="current"';?>><a href="?tab=4">Tab 4</a></li>
 <li<?php if(isset($_GET['tab']) && $_GET['tab'] == 5) echo ' class="current"';?>><a href="?tab=5">Tab 5</a></li>
</ul> 

Basically, I am checking to see if the variable tab is set in the URL, and determining the value of it. I also use the same logic for the tab content. This is the example page with tab 3 displaying. So basically, if the user does not have JavaScript, it would reload the entire page and display the correct tab.

Conclusion

This was just a simple example of jQuery, and the possibilities are endless. Instead of being so quick to use a plugin or someone’s code, try to do it yourself. You will become a much better programmer because of it. Even if you aren’t doing things as efficiently as possible, you will learn something new every time.

Categories