Search

jQuery Tabs

Posted on 18th January 2008 — Tabbing has been common place on the Internet for some time now. Today web sites will make use of tabbing without the page having to reload with the addition of JavaScript.

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.

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>

Comments

  1. Mike On 3rd July 2009 at 14:07

    Pretty much a noob here, but does anyone have an idea why this won’t work at all in IE7? Works fine in FF (3.0.11) of course, but IE seems to be doing absolutely nothing…not even an error.

    I’m using code that was updated for jquery 1.3.2 (someone on this thread included it) $(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>
    

    Any ideas or tips would be great…thanks

    Mike

  2. Mke On 5th July 2009 at 22:07

    K…figured it out. Something to do with the type/charset. I nuked both parameters in the js call and it works fine.

    If anyone out there feels like enlightening me as to why this made IE mad, I’d love to hear it.

    This code didn’t work. I removed the type/charset and it was fine:

    Mike

  3. Alex On 13th July 2009 at 11:07

    Hi, I don’t know very good javascript and also jquery so I’ll ask to you. I would like to know if it’s possible, with this script, set the auto height. The biggest height have to be set for all the other tabs.

    Thank you in advance Alex

  4. Neel On 14th July 2009 at 07:07

    Great tutorial, I tried it and working excellent. I will definitely use it in my future projects.

  5. SUmit On 22nd July 2009 at 14:07

    hi there

    is it possible to use more of these tabs on one single site without copy & paste the code over and over again and include the same .js with a different name?

    Like

    Tab1 Tab2 Tab3

    TABcontent1

    Tab3 Tab4 Tab5

    Tabcontent2

    and so on

    possible?

  6. matthi On 29th July 2009 at 01:07

    Really great stuff, just “stumbled upon” your site.

    I have no clue about jQuery and the whole stuff but that was really very easy to follow. I just wonder how you would extend it to have some fade effect or similar.

    Right now the he visual outcome/the user experience is similar if not equal as if i would have put all the content into an fixed sized div with overflow: hidden

    And yes, I would like to see that in combination with the 2nd example as I donĀ“t want to have menu AND content in one and the same div….

    Thx a lot and best regards

    matthi

  7. Richard Bland On 29th July 2009 at 20:07

    Hello,

    Firstly you sound very much like me on a mic so that is a bit crazy, all the way through I thought I was listening to myself, now that was a trip!

    Secondly, blown away by this tutorial, great tool for someone who is just starting to pick up the basics of JQuery.

    Thirdly, are you available for coding work? Perhaps we can have a chat sometime…

  8. Shovan On 5th September 2009 at 11:09

    Hay, Thanks a lot I have never coded in jquery your tutorial gives me confidence

    Awesome

  9. Evan On 21st September 2009 at 19:09

    I can’t seem to get the URL sniffer function to work (from here http://codedumper.com/otese#13-14,25)

    I’m trying to link directly to a tab or trigger one to visible from within another. Any ideas on how to achieve that?

  10. Eliot Johnston On 23rd September 2009 at 23:09

    Nice, thanks. Got it to work straight away.

  11. Rob On 24th September 2009 at 13:09

    Great tutorial.

    Is there a way to make the tabs ’sticky’ on page refresh.

    When I refresh the page the tabs go back to the first one by default.

  12. Bruce On 3rd October 2009 at 01:10

    I know several others have asked without an answer, but I thought I’d throw my hat in the ring of those wishing, hoping, praying for a way to link to a specific tab within a page using this method. I’d rather not dive further into the jUI stuff if I don’t absolutely have to.

  13. Chau On 9th October 2009 at 20:10

    Hey! I really enjoyed your tutorial, but I needed to modify the script to use hover instead of click. It works fine except when I leave the area it doesn’t disappear. Any ideas? Thanks!

  14. Chau On 9th October 2009 at 21:10

    I figured it out. Here is what I did: $(function() { var tabContainers = $('div.tabs > div'); tabContainers.hide();

            $('div.tabs ul.tabNavigation a').hover(function() {
                tabContainers.hide();
                tabContainers.filter(this.hash).show();
                $('div.tabs ul.tabNavigation a').removeClass('selected');
                $(this).addClass('selected');
                return false;
            }, function() {
                tabContainers.hide();
            });
        });
    

  15. Coco On 11th October 2009 at 07:10

    Hi, many thanks for a great simple script, it works like a charm :)

    Just one question: is it possible to add any effects to it? I mean something like fade, wipe, whatever.

    Either way, loving it, and thanx again, bookmarked and recommending it :)

  16. Mauro On 13th October 2009 at 17:10

    Hi all! first really thanks for this stuff! works great

    I have a problem, i need to put inside each tabs (7) a jquery scroller, but its works only on the first tab!!

    I don’t have any idea how can i fix it! Does anybody can help me??

    thanks a lot M.

  17. Chau On 15th October 2009 at 00:10

    When you have an id or class that contains spaces, such as ‘Hello There’, how do you use it inside of :

    .filter(this.hash)

    It doesn’t seem to like spaces at all…

  18. KC Hunter On 19th October 2009 at 17:10

    Very nice tutorial. There’s a bit of a hickup though when reloading the page which could be corrected using anchors.

    • mind4m.com: for the brain
  19. John Leschinski On 19th October 2009 at 18:10

    Rather then grabing the first tab, is there a way to do this same sort of thing, but have it randomly select one of the tabs?

  20. Abhay On 20th October 2009 at 03:10

    This is really nice article about tabs, but is there a way I can find out currently selected tab id?

  21. Tuscaloosa Graphic and Web Designer On 20th October 2009 at 19:10

    Thanks for the simple tabs tutorial. Its exactly what I was looking for.

  22. Antony On 20th October 2009 at 20:10

    Great work, and this piece of jquery has helped me implement better tabs that the standard jquery tab. : D

    It would be good to know if this supports back, forward and bookmark buttons (remembers which tab was selected when you navigate away from the page, and then hit the back button). I tried using the cookie from Jquery tab, but this did not work.

    I also tried the work around here: http://codedumper.com/otese#13-14,25 but this did not work either. : (

    I’m using this version of tabs:

    $(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(); });

    Any help would be greatly appreciated.

    Thanks

    Antony

  23. Antony On 22nd October 2009 at 18:10

    Trying to get the URL sniffer function to work… which does now after a couple of modifications, but I fear I’ve tinkered with something I shouldn’t have. The only problem now, is that when you return to the page with the tabs on it, the page jumps to the # anchor.

    Here’s what I did to the URL sniffer code (only works if you place it after the original tab jquery). Also, I can’t figure out what the variable should be for tabs - second line of code.

    $(function () {
        var tabs = [];
        var tabContainers = $('div.tabs > div');
        $('div.tabs ul.tabNavigation 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));
            }
        });
    
    // sniff for hash in url, and create filter search 
    var selected = window.location.hash ? '[hash=' + window.location.hash + ']' : ':first'; 
    
    $(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;
    }).filter(selected).click();
    
    
    });
    
  24. Antony On 22nd October 2009 at 18:10

    Well, the code didn’t paste too well, the second line is this:

    var tabs = [];

  25. Antony On 23rd October 2009 at 08:10

    Sorry if I’m boring everyone with my ineptitude.

    Here is an example of my scruffy “sticky tab”: http://www.antonyslinn.com/jquery/tabs/

    As you will see, if you click on the “Company profile” tab, then select the “Edit Company profile” link, then select the “< Back” button (not the browser’s back button) you will see that the sniffer is working, but the page jumps to the anchor.

    Does anyone have any ideas, or the inclination to get this working 100%?

    Would be super if anyone can help.

    Thanks

    Antony

Comments are now closed.