For this tutorial I have created two screencasts demonstrating how to quickly apply a dash of jQuery to different layouts of markup, which, if the markup is well designed, it will automatically degrade nicely without JavaScript enabled. In a future article we will cover default browser functionality (i.e. supporting back, forward and bookmark buttons) and saving tab states.
Conventional and simple markup
Watch the jQuery tabs screencast - part 1 (flash version)
(QuickTime version is approx. 25Mb, flash version is streaming)
View demo and code used in screencast
Typical tabbing structure, and the one used in the demo is usually marked up as follows:
<div class="tabs">
<!-- tabs -->
<ul class="tabNavigation">
<li><a href="#message">Send a message</a></li>
<li><a href="#shareFile">Share a file</a></li>
<li><a href="#arrange">Arrange a meetup</a></li>
</ul>
<!-- tab containers -->
<div id="message">
<p>Lorem ipsum dolor sit amet.</p>
</div>
<div id="shareFile">
<p>Sed do eiusmod tempor incididunt.</p>
</div>
<div id="arrange">
<p>Ut enim ad minim veniam</p>
</div>
</div>
Here’s the jQuery used, though slightly adapted from this screencast:
$(function () {
var tabContainers = $('div.tabs > div');
$('div.tabs ul.tabNavigation a').click(function () {
tabContainers.hide().filter(this.hash).show();
$('div.tabs ul.tabNavigation a').removeClass('selected');
$(this).addClass('selected');
return false;
}).filter(':first').click();
});
Real World example
Watch the jQuery tabs screencast - part 2 (flash version)
(QuickTime version is approx. 30Mb, flash version is streaming)
View demo and code used in screencast
Chris Mahon requested a tutorial that explained how to apply tabbing to markup that doesn’t follow the above markup convention.
In his case, the tabs were in a different DIV to the tab containers, in addition, one item in the UL wasn’t a tab, but used to link to a different page.
Here’s the jQuery tab code used:
$(function () {
var tabs = [];
var tabContainers = [];
$('ul.tabs a').each(function () {
// note that this only compares the pathname, not the entire url
// which actually may be required for a more terse solution.
if (this.pathname == window.location.pathname) {
tabs.push(this);
tabContainers.push($(this.hash).get(0));
}
});
$(tabs).click(function () {
// hide all tabs
$(tabContainers).hide().filter(this.hash).show();
// set up the selected class
$(tabs).removeClass('selected');
$(this).addClass('selected');
return false;
});
});
Taking it further
These screencasts are really designed to help you understand the thought process and how to go about writing the code for the tabs.
In a future article I will explain how to convert this code to a plugin that can be reused on your projects, and what to watch out for when making the code reusable.
Of course, you can always use the jUI Tabs to accomplish the task if you require more dynamic functionality.
You should follow me on Twitter here I tweet about jQuery amongst the usual tweet-splurges!
Related screencasts
Demo
If you find this demo doesn't work as expected, it's possibly due to the demo running from within an iframe. Try running the demo in it's own window.
Source Code
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<title>Tabs</title>
<style type="text/css" media="screen">
<!--
BODY { margin: 10px; padding: 0; font: 1em "Trebuchet MS", verdana, arial, sans-serif; font-size: 100%; }
H1 { margin-bottom: 2px; font-family: Garamond, "Times New Roman", Times, Serif;}
DIV.container { margin: auto; width: 90%; margin-bottom: 10px;}
TEXTAREA { width: 80%;}
FIELDSET { border: 1px solid #ccc; padding: 1em; margin: 0; }
LEGEND { color: #ccc; font-size: 120%; }
INPUT, TEXTAREA { font-family: Arial, verdana; font-size: 125%; padding: 7px; border: 1px solid #999; }
LABEL { display: block; margin-top: 10px; }
IMG { margin: 5px; }
UL.tabNavigation {
list-style: none;
margin: 0;
padding: 0;
}
UL.tabNavigation LI {
display: inline;
}
UL.tabNavigation LI A {
padding: 3px 5px;
background-color: #ccc;
color: #000;
text-decoration: none;
}
UL.tabNavigation LI A.selected,
UL.tabNavigation LI A:hover {
background-color: #333;
color: #fff;
padding-top: 7px;
}
UL.tabNavigation LI A:focus {
outline: 0;
}
div.tabs > div {
padding: 5px;
margin-top: 3px;
border: 5px solid #333;
}
div.tabs > div h2 {
margin-top: 0;
}
#first {
background-color: #f00;
}
#second {
background-color: #0f0;
}
#third {
background-color: #00f;
}
.waste {
min-height: 1000px;
}
-->
</style>
<script src="/js/jquery.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
$(function () {
var tabContainers = $('div.tabs > div');
tabContainers.hide().filter(':first').show();
$('div.tabs ul.tabNavigation a').click(function () {
tabContainers.hide();
tabContainers.filter(this.hash).show();
$('div.tabs ul.tabNavigation a').removeClass('selected');
$(this).addClass('selected');
return false;
}).filter(':first').click();
});
</script>
</head>
<body id="page">
<div class="tabs">
<ul class="tabNavigation">
<li><a href="#first">First</a></li>
<li><a href="#second">Second</a></li>
<li><a href="#third">Third</a></li>
</ul>
<div id="first">
<h2>First</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div id="second">
<h2>Second</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
<div id="third">
<h2>Third</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</div>
</div>
<div class="waste"></div>
</body>
</html>

Play QuickTime version
Play Flash version

Rick On 19th January 2008 at 18:01
I would much prefer to see all the code on the page, rather than in the overflowing div’s. Makes it easier to understand if I can see it in context.
Also, I couldn’t find the CSS for the demo. It would be great if you could provide a download of all files (and graphics, if applicable) for tutorials, so they can be viewed and worked on locally.
Once final thing… love the video demos, showing just how the code is put together, along with the audio explanation of what you’re doing!
Thanks for the work!
Rick
Remy On 19th January 2008 at 20:01
Rick - thanks for the feedback.
The overflow was to do with the theme - so I’ve binned the options for colours and layout, and defaulted it to fluid width. Hopefully this will make seeing the code easier.
I’ll also add links to the source code used in both demos.
Cheers.
mrm On 19th January 2008 at 22:01
The html in my previous post got stripped. What I meant to say whas that the UL element should have class=”tabNavigation”.
Remy On 19th January 2008 at 23:01
@mrm - cheers - I’ve updated that now.
Rick On 21st January 2008 at 03:01
Much nicer and more usable display of the code, Remy.
Thanks!
Rick
Jonathan On 13th February 2008 at 21:02
I’m loving this method, as for my current project I don’t really require any dynamic functionality or the significant numbers of options that the UI plugin provides. I do have one question, though.
Is it possible to switch the tab based on the querystring value (i.e. http://example.com/page.html?tab=tabname)? If so, how can I achieve this?
Thanks so much! Jonathan
Max On 18th February 2008 at 20:02
Great tutorial, thank you very much! Here come a couple of ‘eye-rolling’ newbie questions:
Has this been tested in various browsers? I’ve tried it in Firefox, IE, as well as in Opera, and it’s not working as expected in the latter two.
I’ve tried looking up more info on the ‘.hash’ selector (and selecting with ‘this.hash’ in general), and couldn’t find much. Any links to resources on that would be greatly appreciated.
Thanks!
Remy On 19th February 2008 at 01:02
@Max - regarding testing, I tend to test in Firefox, Safari and IE (usually 7). I’ve looked at the examples in Opera, and the second one is not working for some reason (that I’ll look in to).
I’ve also noticed that Chris Mahon’s original CSS for the ‘ThumbSlap’ page has been taken down - so I’m following up to get that fixed so it matches the screencast.
Finally, the .hash that I used: it’s not a selector. In the context of the click event, ‘this’ is set to the anchor element. The anchor element has an attribute of ‘href’. As a DOM node, it also has a property called ‘hash’. This is the part in the href from the hash symbol onwards (i.e. mypage#tab1 - #tab1 is the hash).
As such, we’re able to use the variable this.hash to use it as the element ID we’re searching for using jQuery.
I hope that helps.
Max On 19th February 2008 at 15:02
Remy,
Thank you very much for your prompt response! That definitely clears things up. I guess if there’s no click event then I’ll have to find an alternate way of getting to the right tab container div.
Thanks again for the great tutorial!
tom On 11th March 2008 at 22:03
Thanks for the tutorial. I have found that the second method you use does not work in either IE6 or IE7? Am I alone in finding this?
I have attempted a similar mehtod it cannot get it to work. It works ok in firefox and in safari but IE - not im afraid. Any suggestions?
Here is my attempt;
http://www.tomhorner.com/websites/starkey/productmenu.php
Max On 12th March 2008 at 15:03
Tom,
What could be the problem is the bit where pathnames are being compared. I found out that IE and Firefox give out different strings for location.pathname and this.pathname.
I recommend you read the section titled “What’s in a path name?” at this address: http://www.learningjquery.com/2007/08/animated-scrolling-for-same-page-links
It also contains a nice fix which got my script working.
Hope it helps!
Max On 12th March 2008 at 15:03
Is it just me or does clicking on tab links in Opera throws you to the top of the page? I really don’t get why, since the function returns false… Any ideas?
By the way, is there a tool out there which is similar to Firebug, only for Opera?
tom On 15th March 2008 at 20:03
Hey Max, thanks so much for the link - worked a treat! Solved my problem straight away.
Rod On 25th March 2008 at 11:03
Hi Remy, I think this a great source for many people. I personally love the way you show your ideas and code. I´m a designer who has now a complete new world of possibilities thanks to jquery and sites like yours. Please keep going! Regarding these tabs, which would be the code needed to load each tab content from external pages? Do you think the hash feature would still work with such a change? Thanks!
eph On 14th April 2008 at 20:04
hey this is great! is the jquery.js free to use with citations? and if so what type of citing is required?
Travis On 15th April 2008 at 22:04
Hey Remy, Fantastic tutorial and site all around. Love it.
Any status updates on the stylesheet for:
http://jqueryfordesigners.com/demo/thumbslap.html
I’d really like to see the demo in action, style and all. Thanks.
Marcus On 18th April 2008 at 22:04
Hey Remy,
First off, love the site!
Second, for some reason, the I can’t get the first example of jQuery Tabs to play nicely in IE6. (IE6 you drive me flippin’ batty!)
Any ideas? Thanks man!
krew On 22nd April 2008 at 05:04
I just wanted to thank you for putting together such a great jQuery resource. The tutorials you’ve posted have been very helpful in my site development, and I look forward to seeing what you come up with next.
Mohammed Alaa On 14th May 2008 at 11:05
hi Remy,
i use right now your method and i have to admit it it’s a cutting edge solution for most designers.
but i have only one problem in IE7 please check it here: http://www.be-genius.com/projects/JobsterLive/index.htm
Thanks alot, Mohammed Alaa
Quin On 4th June 2008 at 16:06
Thanks for the tutorial!
I have one question… I have created 2 instances of this tab-box on the same page. Therefore, 2 divs each containing 3 tabs. The problem is this. When one tab is selected in one box, the “selected” class is removed from the other box and the content gets hidden.
Is there a way to have more than one div containing tabs that will maintain the “selected” class?
Many thanks
Abu On 16th June 2008 at 10:06
Hi there,
Can you tell me how we can select a tab through the URL? No matter what I feed through the URL, its always the first tab which is opened.
Thanks
Remy On 16th June 2008 at 11:06
@Abu - I’ve quickly knocked together the code change you need to do this - they’re highlighted in the link below:
http://codedumper.com/otese#13-14,25
Abu On 16th June 2008 at 17:06
Thanks. Worked like a charm!
How does “a = b ? c : d” work? I’ve seen that type of code in many places, but never really understood it.
Thanks again.
Remy On 16th June 2008 at 17:06
@Abu - it’s basically a one line ‘if then else’:
http://en.wikipedia.org/wiki/Ternary_operation
Says that b is the test, a is equal to c if b is true, and d if b is true.
Abu On 16th June 2008 at 18:06
Thanks again.