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 posts

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. symeon On 11th November 2009 at 04:11

    Hi.

    Thanks for a good script:) I have a question, why the version 2 does not hide other div, second and third. And also, why does not work properly in Chrome and IE?

  2. moofar On 13th November 2009 at 03:11

    Hi.

    Can someone advise me why the code does not retract the other panels at each other?

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

  3. Ged On 16th November 2009 at 08:11

    Wow thank you so much for taking the time to make this tutorial. Extremely helpful and totally in reach.

    Thank you!

  4. Andrew On 17th November 2009 at 23:11

    Everything works for me using the unconventional method, except the tab doesn’t hide on load, only on click.

    site is clients.honestbros.com/capstone/experience/issues.html

  5. Chris On 21st November 2009 at 16:11

    How can you make it where the content in the separate div tags does not show while the page is loading. All the divs stack on top of each other right now until the page is loaded, then it goes good. This is detracting to a reader though. I could make my page faster, but I’d have to leave the content off. :)

  6. Lorenzo On 27th November 2009 at 15:11

    The problem with jQuery Tabs is that if you have ULs and LIs inside the content of first, second and third tabs every gets mixed and corrupted.

    This there a way to isolate the content inside a tab? I tried using class but the only thing I can do is add span for each element.

    Regards,

  7. bresson On 30th November 2009 at 18:11

    First, thanks for the tutorial and source code - I’m using it on all my projects! Second, is there a way to activate a particular tab depending on which page was used to access the tab page? Here’s the code I’ve been using and the first tab is default. For instance, if page (full URL) is http:pagefromsomwehere.com clicks to access the tab page, can I revise the function to show the second tab but in all other cases, retain the first tab as default. Thanks a million.

    function activateTabs () { 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();
    

    }

  8. Rasmus Fjord On 3rd December 2009 at 11:12

    Hey …

    I have a small prob … in ie6(god forbid this browser) its not showing the border(have a picture of it here.)

    http://dl.dropbox.com/u/1358333/ie6%20bug.png

    I wrote something about putting the border inline .. but maybe its just me but couldnt get it to work ? anyone got a fix ?

  9. ony On 19th December 2009 at 21:12

    Hi , thanks for the tutorial

    implemented it and works perfect but , just have one question :

    is it possible to hide all content of all 3 tabs on the page load , and only display and i click on a tab?

    hope u understand what i mean cose my english is bad ,

    Thanks.

  10. Judd Dunagan On 8th January 2010 at 16:01

    Remy,

    1st I would like to thanks for the excellent post. I used the tabs on this page. http://www.georgeforemancooking.com/c-8-our-products.aspx They work great, I am having some trouble getting them to work on roll over instead of on selected. I would be greatful if you could point me in the right direction.

    Thanks, Judd

  11. Judd Dunagan On 8th January 2010 at 17:01

    Ony,

    I believe this is what your are looking for,

        <script type="text/javascript" charset="utf-8">
        $(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();
        });
        });
       </script>
    

    What I need is for the 1st tab to show up and not hide all. Any ideas?

  12. Judd Dunagan On 8th January 2010 at 17:01

    Ok Guys I figure out how to make the 1st tab show and instead of selected, it will hover.

        <script type="text/javascript" charset="utf-8">
        $(function() {
            var tabContainers = $('div.tabs > div');
            tabContainers.hide().filter('#first').show();
        $('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();
        });
        });
       </script>
    
  13. Kevin On 20th January 2010 at 20:01

    Really enjoy your screencasts. Good pace, clean design, even some insight into how you troubleshoot problems (not in this one, but a later one).

  14. NEELA On 22nd January 2010 at 15:01

    Hi, The j Query tabs very good to use,I used them in my applciation .It worked good for IE but it is not working in Mozilla .In mozilla iam unable to click on the second tab.we should add any special things for mozilla to use it.

    Waiting for reply…

Leave your own comment
  • http://