Advanced jQuery Tabbed Box Techniques

Published January 25, 2009 by CSS Newbies.

animated tabbed box interface

Last week’s article covered how to build a tabbed box interface, starting with Photoshop, and moving through XHTML and CSS to our basic jQuery functionality. If you missed it, I would highly recommend starting your reading there. This article will show you how to use jQuery to make your tabbed interface more attractive and interactive. Specifically, I’ll show you how to:

  • Make your tabs all the same height
  • Automatically rotate through your tabbed content
  • Stop the rotation when the user is interacting with the content

Equal Height Tabs

The tabbed interface we built last week was fully functional, but one nicety I’d like to add is the option to have all your tabs be the same height – a height that is determined by the content within the tabs, not any number I arbitrarily determine in advance.

While there are several ways to calculate and apply height in jQuery, the fastest and easiest means to our end would be to use the equalHeights jQuery plugin I developed and wrote about recently. By using that plugin, we’d only have to make a single addition to the “document ready” portion of our jQuery:

$(".tabbed-content").equalHeights();

This will cycle through all of our tabbed content divs and equalize their heights based on the height of the tallest div. The benefit of this is the content around our tabbed box won’t shift up or down each time the user switches tabs, resulting in a more pleasant visual experience.

Rotate Through Tabbed Content

While tabbed boxes like the one we’ve built are a great way to fit a large amount of content in a small space, they do have one drawback: many users never click through the tabs to see what all is offered, meaning they only ever see the content on the first tab. My proposed solution to this problem is to automatically rotate through the tabs.

This solution has two benefits: first, the movement is more likely to catch the users’ eyes, increasing the chances they’ll notice the tabbed box in the first place. Second, it allows your users to see all the content your box contains instead of just the first tab.

Making this adjustment to our jQuery requires edits in several areas, so I’ll show you the new code in its entirety before explaining what it all does:

var currentTab = 0; 
var rotateSpeed = 5000;
var numTabs;.
var autoRotate;

function openTab(clickedTab) {
	var thisTab = $(".tabbed-box .tabs a").index(clickedTab);
	$(".tabbed-box .tabs li a").removeClass("active");
	$(".tabbed-box .tabs li a:eq("+thisTab+")").addClass("active");
	$(".tabbed-box .tabbed-content").hide();
	$(".tabbed-box .tabbed-content:eq("+thisTab+")").show();
	currentTab = thisTab;
}

function rotateTabs() {
	var nextTab = (currentTab == (numTabs - 1)) ? 0 : currentTab + 1;
	openTab($(".tabbed-box .tabs li a:eq("+nextTab+")"));
}

$(document).ready(function() {
	$(".tabbed-content").equalHeights();
	numTabs = $(".tabbed-box .tabs li a").length;
	
	$(".tabbed-box .tabs li a").click(function() { 
		openTab($(this)); return false; 
	});
	
	autoRotate = setInterval("rotateTabs()", rotateSpeed);	
	$(".tabbed-box .tabs li a:eq("+currentTab+")").click()	
});

The first variable, currentTab, is unchanged from our first iteration. But then we’ve added three new variables:

  • rotateSpeed is the number of milliseconds to wait before switching tabs.
  • numTabs is a variable that will contain the total number of tabs in our box. We’re initializing it at the beginning so we can use it in all our functions.
  • autoRotate is a variable we’ll use later.

Our openTab function hasn’t changed. If you’d like to understand how it works, please refer to the first article.

Next we’ve written a new function called rotateTabs. This function will handle the math required to determine which tab should be opened next. First we set a new variable, nextTab. What we set nextTab to depends on which tab we’re on currently. The function looks at currentTab: if currentTab is our last tab in the list, it starts back over at the beginning (the tab with an index of 0). Otherwise, nextTab is simply the next tab in the list. Once we’ve determined our next tab, we call the openTab function, which prevents us from having to duplicate all that heavy lifting.

We’ve added two lines to our document ready function. The first sets the numTabs variable to be the number of tabs in our box. We don’t populate this variable until the document is ready, because otherwise it will try to count the tabs before our tabs have loaded and will return a length of -1 (aka, none found).

The second bit we added is towards the end, where we set autoRotate. In autoRotate we’re calling the JavasScript setInterval function, which executes a piece of JavaScript on a regular interval. As we’ve written it, we will be calling our autoRotate function every “rotateSpeed” milliseconds. This means that when our document loads, it will wait that many milliseconds, then switch to the next tab, then pause again, then switch again infinitely.

Pretty neat, huh? You can see this functionality in action here.

Stopping the Rotation

Now, automatically rotating your tabs is a pretty awesome effect, but at some point you’re probably going to want that rotation to stop. Specifically, you don’t want your tabs switching when your users are interacting with them.

I tested several scenarios on when and how to stop the tabs from rotating before deciding on how I’m doing it here. It only requires editing a couple of lines from our document ready function:

$(document).ready(function() {
	$(".tabbed-content").equalHeights();
	numTabs = $(".tabbed-box .tabs li a").length;
	$(".tabbed-box .tabs li a").click(function() { 
		openTab($(this)); return false; 
	});
	$(".tabbed-box").mouseover(function(){clearInterval(autoRotate)})
	.mouseout(function(){autoRotate = setInterval("rotateTabs()", rotateSpeed)});
	
	$(".tabbed-box .tabs li a:eq("+currentTab+")").click()
	$(".tabbed-box").mouseout();
	
});

Here we’ve replaced our setInterval function with something a little more complex. We’re now using both setInterval and clearInterval (which stops setInterval), and we’re applying them when the user’s mouse interacts with our tabbed box.

Specifically, we’re letting the box auto-rotate whenever the mouse is nowhere near the box, and stopping the box from rotating whenever the mouse is over the box. This means that as long as the user has the mouse over the box, as if they were reading, or clicking through the tabs, or clicking on something inside one of our tabs, the tabs wouldn’t switch on them. But as soon as they’re done interacting with the box, it’ll switch back to its regular rotation.

This does require one extra line at the end of the script, to force a “mouseout” event on the tabbed box, which gets things rotating by default.

You can see our fully functional tabbed interface here. Give it a try: watch it rotate through, and then try interacting with the box a bit. You’ll see that the tabs don’t automatically move, as long as you’re actively engaged with the box.

And that’s that! I hope you’ve found this mini-series helpful, and I’d love to see how you’ve implemented this idea on your own websites. Drop me a line in the comments below if you do.