Sweet AJAX Tabs With jQuery 1.4 & CSS3

Sweet AJAX Tabs With jQuery 1.4 & CSS3

Organizing the content of a page in a both intuitive and eye-catching manner, is a must in modern web design. One principle that has been around for some time is dividing text into tabs. This allows you to squeeze much more content in a seemingly limited space and provide a structured way of accessing it.

Today we are making an AJAX-powered tab page with CSS3 and the newly released version 1.4 of jQuery, so be sure to download the zip archive from the button above and continue with step one.

Step 1 – XHTML

As usual, we start off with the XHTML markup.

demo.html

<ul class="tabContainer">
	<!-- The jQuery generated tabs go here -->
</ul>

<div class="clear"></div>

<div id="tabContent">
	<div id="contentHolder">
		<!-- The AJAX fetched content goes here -->
	</div>
</div>

If you think the markup looks too simple to be true, you are right. As you can see, we are missing the code for the tabs, because it is inserted dynamically by jQuery on page load. This makes it extremely easy to add new tabs as you only need to add them on the JavaScript side (more on that in a moment).

demo.html

<li>
	<a href="#" class="tab green">Tab two
		<span class="left"></span>
		<span class="right"></span>
	</a>
</li>

This is the markup that is inserted by jQuery for each tab. It consists of a LI element positioned inside of the .tabContainer unordered list above, and contains a hyperlink with two spans. Those show the left and the right part of the background image and thus enable the tabs to stretch and give room for the text label inside.

Also notice the green class of the link – it determines the background, text color and hover state of the tab, as you will see in the next step of this tutorial.

Sweet AJAX-ed Tabs With jQuery 1.4 & CSS3

Sweet AJAX-ed Tabs With jQuery 1.4 & CSS3

Step 2 – CSS

With the markup in place, we can take a more detailed look at the styling of the tab page.

styles.css – Part 1

.tabContainer{
	/* The UL */
	float:right;
	padding-right:13px;
}

#contentHolder{
	background-color:#EEEEEE;
	border:2px solid #FFFFFF;
	height:300px;
	margin:20px;

	color:#444444;
	padding:15px;
}

#tabContent{
	background-color:#333;
	border:1px solid #444;
	margin-top:-15px;
	width:100%;
}

#tabContent, .tabContainer li a,#contentHolder{
	-webkit-box-shadow:0 0 2px black;
	-moz-box-shadow:0 0 2px black;
	box-shadow:0 0 2px black;
}

.tabContainer li{
	/* This will arrange the LI-s next to each other */
	display:inline;
}

.tabContainer li a,.tabContainer li a:visited{
	/* Styling the hyperlinks of the tabs as colorful buttons */

	float:left;
	font-size:18px;

	/* display:block allows for additinal CSS rules to take effect, such as paddings: */
	display:block;

	padding:7px 16px 1px;
	margin:4px 5px;
	height:29px;

	/* Giving positioning */
	position:relative;

	/* CSS3 text-shadow */
	text-shadow:1px 1px 1px #CCCCCC;
}

Here we use a number of CSS3 rules that add up to the overall feel of the page. First is the box-shadow property, which adds a shadow below the tabs, the #tabContent div and the #contentHolder.

After this we have the text-shadow property, which adds a light-colored shadow (more of a outer glow in this case), which adds an inset feel to the text of the tabs.

styles.css – Part 2

#overLine{
	/* The line above the active button. */
	position:absolute;

	height:1px;
	background-color:white;
	width:90px;

	float:left;
	left:1px;
	top:-5px;
	overflow:hidden;
}

#main{
	margin:0 auto;
	position:relative;
	width:700px;
}

ul .left{
	/* The left span in the hyperlink */

	height:37px;
	left:0;
	position:absolute;
	top:0;
	width:10px;
}

ul .right{
	/* The right span in the hyperlink */

	height:37px;
	right:0;
	position:absolute;
	top:0;
	width:10px;
}

/* Styling the colors individually: */

ul a.green{	background:url(img/green_mid.png) repeat-x top center;	color:#24570f;}
ul a.green span.left{ background:url(img/green_left.png) no-repeat left top;}
ul a.green span.right{ background:url(img/green_right.png) no-repeat right top;}

/* .. Analogical styles for the red, blue and orange color .. */

/* The hover states: */
ul a:hover{	background-position:bottom center; text-decoration:none;}
ul a:hover span.left{ background-position:left bottom;}
ul a:hover span.right{ background-position:right bottom;}

.preloader{
	display:block;
	margin:120px auto;
}

In the second part of the code, you can see that we define different backgrounds for the hyperlink and the left and right spans, depending on the color class that is assigned. This way we can successfully change a number of CSS styles and as a result have a completely different design of the tab, by just setting a different class name for the hyperlink.

The Tabs

The Tabs

Step 3 – jQuery

This is where the magic happens. First we need to include the jQuery library in the page:

demo.html

<link rel="stylesheet" type="text/css" href="styles.css" />

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script>
<script type="text/javascript" src="script.js"></script>

We include the latest version of jQuery from Google’s CDN and immediately after it, we add our own script.js file, which contains all of our scripts.

Here is a detailed explanation of what exactly jQuery does:

  • The page is opened in a visitor’s browser and the jQuery library is downloaded from Google’s Content Depository Network;
  • $(document).ready() is queued for execution and the function that is provided as a parameter is run when the DOM has finished loading;
  • The Tabs object is looped with the $.each() method and individual <LI> elements are created and appended to the .tabContainer <UL> (covered in step one);
  • Event listeners for the click event on the tabs are set up.

You can view the code below:

script.js – Part 1

$(document).ready(function(){
	/* This code is executed after the DOM has been completely loaded */

	/* Defining an array with the tab text and AJAX pages: */

	var Tabs = {
		'Tab one'	: 'pages/page1.html',
		'Tab two'	: 'pages/page2.html',
		'Tab three'	: 'pages/page3.html',
		'Tab four'	: 'pages/page4.html'
	}

	/* The available colors for the tabs: */
	var colors = ['blue','green','red','orange'];

 	/* The colors of the line above the tab when it is active: */
	var topLineColor = {
		blue:'lightblue',
		green:'lightgreen',
		red:'red',
		orange:'orange'
	}

	/* Looping through the Tabs object: */
	var z=0;
	$.each(Tabs,function(i,j){
		/* Sequentially creating the tabs and assigning a color from the array: */

		var tmp = $('<li><a href="#" class="tab '+colors[(z++%4)]+'">'+i+' <span class="left" /><span class="right" /></a></li>');

		/* Setting the page data for each hyperlink: */

		tmp.find('a').data('page',j);

		/* Adding the tab to the UL container: */
		$('ul.tabContainer').append(tmp);
	})

The source above is the first part of script.js, which you can find in the download archive. You can add your own tabs on the page by inserting a new property to the Tabs object. The left part holds the name of the tab in single quotes, and the right part (after the semicolon) contains the AJAX URL which is going to be fetched and displayed in the #contentHolder div.

In the following second part of the script, you’ll see jQuery 1.4 in action, as we create a new div element (that acts as the line above the active tab) and pass an object with the ID and CSS properties instead of setting them separately with the .attr() and .css() methods.

script.js – Part 2

	/* Caching the tabs into a variable for better performance: */
	var the_tabs = $('.tab');

	the_tabs.click(function(e){

		/* "this" points to the clicked tab hyperlink: */
		var element = $(this);

 		/* If it is currently active, return false and exit: */
		if(element.find('#overLine').length) return false;

 		/* Detecting the color of the tab (it was added to the class attribute in the loop above): */

		var bg = element.attr('class').replace('tab ','');

 		/* Removing the line: */
		$('#overLine').remove();

 		/* Creating a new div element with jQuery 1.4 by passing an additional object parameter: */

		$('<div>',{
			id:'overLine',
			css:{
				display:'none',
				width:element.outerWidth()-2,
				background:topLineColor[bg] || 'white'
			}}).appendTo(element).fadeIn('slow');

 		/* Checking whether the AJAX fetched page has been cached: */

		if(!element.data('cache'))
		{
			/* If no cache is present, show the gif preloader and run an AJAX request: */
			$('#contentHolder').html('<img src="img/ajax_preloader.gif" width="64" height="64" class="preloader" />');

 			$.get(element.data('page'),function(msg){
				$('#contentHolder').html(msg);

 				/* After page was received, add it to the cache for the current hyperlink: */
				element.data('cache',msg);
			});
		}
		else $('#contentHolder').html(element.data('cache'));

 		e.preventDefault();
	})

	/* Emulating a click on the first tab, so that the content area is not empty: */
	the_tabs.eq(0).click();

});

Notice the use of the jQuery data() method throughout the code. It assigns arbitrary data to an element by calling the method with two parameters $(‘#selector’).data(‘label’,”String Data”). This assigns the string “String Data” to the element and we can later access it (or check if it has been set) by calling the data method without the second parameter.

This way we set up a simple caching system for the AJAX requests. The first time an AJAX call is made, the text of the response (held in the msg variable) is stored at data(‘cache’). On consecutive calls we check for this cache variable and return it instead of firing a new request. This way we remove unnecessary server load and improve the responsiveness of the tabs.

Active Tab

Active Tab

With this our sweet AJAX-ed tabs are complete!

Conclusion

Today we created AJAX – enabled colorful tabs with jQuery 1.4 and CSS3. We also implemented a simple caching mechanism using the data() method. The source code is easily modifiable and adding new tabs is as easy as adding new properties to the Tabs object.

If you liked this tutorial, be sure to follow us on twitter for early previews and interesting links from the world of web development.

What do you think? How would you improve this example?

Join our newsletter and get our PSDs!19,479 people learn about HTML5, JS and more. Join them!

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and it still is his favorite side project.

57 Comments

  1. Nice Job Martin.

    I've got a client's intranet page I can test this on this week.

    Thanks for the collective.

    Michael

  2. David Moreen says:

    This is just a perfect tutorial for the week. Just yesterday I was looking around for a tab system.

  3. Xesbeth says:

    Nice tutorial Martin!
    Thanks a lot !!! :)

  4. doug says:

    Excellent work. Always more interesting to follow a tutorial all the way through when the final result is interesting/useful.

  5. Simply awesome, couldn't the buttons be made using a single image as a sprite as well, but all in all a great tut! Love seeing CSS3 mixed with jQuery!

  6. Martin Angelov says:

    Thank you for the comments!

    @ Montana

    Yes, you could use a sprite. Would be a bit tricky in the CSS part to ensure cross-browser compatibility, but it would be worth it.

  7. Liam says:

    But what happens when the user doesn't have JavaScript enabled...

    It should degrade gracefully.

  8. That’s great !
    jquery is the best js framework
    thanks alot

  9. Fernandos says:

    It's a great tutorial as ever!
    You know howto catch every single wow moment in a dev's life ;)

    Don't take me bad, it's just constructive critic. I wouldn't mind to give a sh't if I didn't really like this site!

    "Tutorialzine is hella cool! Really!"

    I don't know howto make this script unobstrusive, so I'm absolutely with you :)

    http://en.wikipedia.org/wiki/Unobtrusive_JavaScript

  10. Martin Angelov says:

    @ Liam

    You can implement graceful degradation by adding the content of the different tabs as content to the contentHolder div. It will also be available to search engines.

    The content of this div gets replaced immediately on page load if JS is enabled, so it would be practically invisible for visitors supporting JavaScript (who will enjoy the full experience).

  11. Guario Rodriguez says:

    What a great tutorial. I've been looking for a lightweight way of creating AJAX tabs and this is exactly what I was looking for.

    Keep up the great work.

  12. pakpenyo says:

    Great tutorials! I've done try this to my project and its really nice. Thanks.

  13. John says:

    Can I just host jQuery page on my server or do I have to do a direct link to Google jQuery page? You know, just in-case Google decided to pull the plug and leave my website broken?

  14. Martin Angelov says:

    @ John

    Loading it from Google's CDN actually benefits your page loading time. Browsers can download a maximum of two JS files from a domain at once, so you free up a slot by moving jQuery to google's network.

    Rest assured that they won't pull the plug anytime soon.

    If you want more control over your scripts, hosting it on your server will be as easy as replacing that <script> line at the top of demo.html (make sure that you use version 1.4 though).

  15. Soryn says:

    hi Martin,
    is an amazing tutorial, didn't knew this combination was that powerful... I'm kind of a novice to this technology

    I need a small advice about creating a "sub tab", kind of a "secondary menu"... it should be defined in the "script.js" by telling him that some of the tabs are at a secondary level.
    maybe an if-else state should solve the problem but i have no idea how and were to define it.

    this is an example of what i mean exactly:

    Marketing

    Andy Hodges
    Trey Gregory

    Engineering

    Karen Joslin
    Sheila Malone
    Karl Heinz

    ---------------------------------------------------------------

    any help will be grateful
    thanks in advance

  16. SechD says:

    Thanks for the tutorial. I set this one up on our home page and gave credit on our credits page. http://www.swiftindavis.com/about/web-site-credits/

  17. tella says:

    Any way to animate the pages when they load like a fade in

  18. Bernardo says:

    Thanks a lot! Nice tuto

  19. Mubeen says:

    Thanks for this nice tutorial. I am working on a requirement with sub-tabs ie. the tabs have their own set of sub tabs as horizontal navigation system. Can you help with some pointers on making the sub tabs work?

  20. Sivaranjan says:

    Thats one fine example of what CSS can do ! I am so impressed, I am adding this tutorial to my CSS aggregator site. Hope you dont mind.

  21. Ben says:

    Great tutorial, I'm thinking about using it for a project.

    When a tab is clicked, the line above the tab fades in. Could this effect also be applied to the content? How to get started on this?

  22. Tasha says:

    Hi

    I am new to web design and I find this to be an excellent tutorial. I will like to try this for my new project. However, when I download the demo the external files do not load into the div. I don't know much about javascript but the paths same to be correct. Can you tell me what I need to do to see the content?

    Thanks

  23. Wayne says:

    Great Tutorial! I made a vertical version and I'm offering it for FREE on my site. http://www.revitalagency.com/vertical-sweet-ajax-tabs-with-jquery/

  24. greenbandit says:

    i have 12 tabs to show, how i can hide the tabs and only show next / prev tab?

  25. Razan says:

    This is a great example of tab. But, I need small modification in this can we make the titles in the tab dynamic?
    For example I need to fetch the title of the tab from the query from the tables instead defining in the variable.

    Can anyone please help me on this? I would be grateful if any one can help me on this issue.
    Thank you.

  26. e11world says:

    This is actually pretty sweet and thanks for greenbandit for the nice update. I would only make sure the selected state works for that one though. Thanks!

  27. Eli says:

    Hey, just wondering but how would you add a .css() or .addClass() to an active tab?

    Not really good with jQuery but I was seeing how it somewhat does this with the line overhead, but the code is specific to hiding and showing that overhead div.

    What would be the code to change the css or class for an active tab?

    thx!

  28. Eli says:

    hey, is there a way to add history support for these tabs?

  29. Colvin says:

    So I noticed that when I have the .get pull the page data that, if it is php, the server doesnt process the file, it just returns the text of the php document... Any way to request the container data post php compile?

  30. Colvin says:

    For the record. I fixed the issue. It was really a matter of it being way to late in the morning.

  31. Thanks! I'll use this one for my latest project! :)

  32. Jamie says:

    AweSome tutorial... but .. it doesn't display properly in Google Chrome. The content doesn't generate.
    Thanks again for the great tutorial.

    1. Avner says:

      The problem comes from using another version of jQuery than 1.4.0

      I am trying to find a ckue and will post it here if I succeed

  33. Dumah Brazorf says:

    I have the same issue with chrome. Any suggestion?

  34. Dumah Brazorf says:

    Ok I found that is a "feature" of chrome when opening pages on your hd. On a webserver there's no problem.
    http://stackoverflow.com/questions/4208530/xmlhttprequest-origin-null-is-not-allowed-access-control-access-allow-for-file

    Thanks for the tutorial.

  35. Saurus says:

    Is it possible to convert it to jquery 1.7?, it doesnt load contentholder when i switch it to 1.7

  36. Oh I have one question...
    how to make .tabContainer in center positioin?
    I think isn't good to make padding-right:-50px;

  37. Marcel says:

    Hi there!

    A great script, thx a lot for that!

    But I wonder if it's possible to dynamically fill in the jQuery-tabs and the AJAX-fetched parts.

    I want to use these tabs for a webshop, where you have a lot of different formats and sizes, which are displayed via php. So how can I tell the script to use these php-generated data instead of predefining the Tabs-Title and the content-link...

  38. Philippe says:

    Great Script!

    I am actually trying to put in the tab a googlemap v3 - but it just dosnt work... did someone already make successfully? and how to do it? Iam desperate and already working 3 days on it and kinda give up... the map just doesnt show up... :-(((

  39. daveonearth says:

    Having a lot of fun with your tuts and especially this one.

    I have an annoying issue when I try and make the slider as a full div at the top, I cant get the #headerSlideText to be part of the animation?? The text just sits above the header....

    Can you think of any reason? I am losing my mind. I do have hacked up jquery all over :P

  40. Thank you for the nice tabs! I have a question, will the content of the tabs be indexed by search engines?

  41. Cv3 says:

    @اسعار الذهب اليوم No :)

  42. Youwraj says:

    I'm not able to add more tabs here, I tried but not able to add, please give me more details for adding more then 4 tabs

  43. Ryan says:

    Hi there.. great tutorial, is there any way to get this unobtrusive???

    i mean i want to add a form inside the container.

  44. Martin says:

    Wonderful tutorial. It is just what i was looking for :)

  45. Martin says:

    i am having trouble with adding tabs.

    In the .js file i added:
    'Tab five' : 'pages/page5.html'

    The result was having no tabs at all

    1. Avner says:

      Have you noticed the %4 (modulo 4)
      Make it%5, it will work

  46. Daria says:

    I'm having the same disappearing issue when trying to add a fifth tab. Did anyone figure out a fix?

  47. Daria says:

    Nevermind, I figured it out. All you have to do is create a copy of the image files to designate which you want to use for the tabs after the fourth one.

    As in, create a second copy of the blue tab images and label them as blue2, then add blue2:'blue', under the list of colors available var topLineColor = { .

  48. Avner says:

    Had a problem with values above 127, as Alt130 which translates as 'é' but rendered as a square (gibberish).
    Has anyone resolved this?

    TIA

    1. Avner says:

      Solved. I saved the pages in utf-8
      and added charset meta tag

  49. Lars says:

    Hi Martin
    Nice tutorial, but it has a very serious flaw, which unfortunately seems to be a problem with most of the CSS demoes I have found.
    It has completely disabled keyboard navigation. There are millions of users out there, who only when absolutely forced, are using the mouse. For those I think pages designed like this, will quickly be abandoned in favour for more user friendly sites.
    How would you expand your example to support normal keyboard interaction?

  50. Hi, Martin. Great tutorial. I have a question. What to do for insert internal links? Example: In the 'tab two' I want insert many images with links. What to do? Thanks!!!

  51. brian12 says:

    When I download the sample and try to to load it without modifying anything it does not work. The white space under the tabs remains empty no matter what tab i select. Do I need to do something to set up?

    1. Peccavio says:

      The demo's Ajax will not run when accessing as a file.
      If placed on a sever and accessed as a url .... works fine

  52. Carlos says:

    Hi, Awsome tutorial,

    I´m using it as you can see here: http://kasaji.com/observatorio/tabs/demo.html . I would like to know if it´s possible to set a different appearence for the current tab, the one that has been clicked.

    Carlos Pinedo

  53. Shady says:

    Thanks Martin for the post,
    Nice tutorial, but it has a very serious flaw, which unfortunately seems to be a problem with most of the CSS demoes I have found. It has completely disabled keyboard navigation. There are millions of users out there, who only when absolutely forced, are using the mouse. For those I think pages designed like this, will quickly be abandoned in favour for more user friendly sites. How would you expand your example to support normal keyboard interaction?
    Thanks

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links