Better jQuery Tabs Plugin

Tabs!
Delicious, light and sugar-free

Tabs!
Delicious, light and sugar-free!
This is a tight little jQuery tabs plugin that will activate and prevent scroll on load when there’s a URL hash, or do nothing if the hash isn’t one the tabs. It’ll also check if there are links to other tabs in the content. It’s got object literal organization and a little fun progressive enhancement.

Once again, I found a standard-use script lacking magic, and this time it was my group’s go-to tabs plugin. It used a standard flavor of JS without leveraging any library, and it was bad. Switching between tabs took about a second, and even more was added to page load.

By using jQuery, we can cut that to a tiny fraction, while still keeping all the same functionality.

Tabs = {
  // Changes to the tab with the specified ID.
  GoTo: function (contentId, skipReplace) {
    
    // Change current active tab
    $('.toc li.current').removeClass('current');
    $('.toc li a[href="#' + contentId + '"]').parent().addClass('current');
    
    // Change current active content 
    $('.tabs_container .content').hide();
    $('.tabs_container .content').filter('#_' + contentId).show();
  
    // Change the address bar.
    if (!skipReplace) window.location.replace("#" + contentId);
  },

  Init: function () {

    var contentId,
      tabList = [],
      hash = window.location.hash.substring(1); 
      // Hash starts with second character
      // Underscore in "_hash" content ID parameter prevents scroll on load
    
    // Array of tabs  
    $('.tabs_container .toc li a').each(function(){
      tabList.push($(this).attr('href').split('#')[1]);
    });
    
    // If there's a URL hash and it's in the array, activate it
    if ( (window.location.hash) && ($.inArray(hash,tabList) != -1) ) {
      contentId = hash;
    }
    // If the URL hash is not in the array, activate the first tab
    else {
      contentId = $('.toc li a:first').attr('href').split('#')[1];
    }
    
    if (contentId) Tabs.GoTo(contentId, true);
    
    // Attach onclick event to all the anchor links in the table of contents.
    $(".toc li a").click(function(){
      // Get the name of the anchor of the link that was clicked.
      Tabs.GoTo(this.hash.substring(1));
      return false;
    });

	// Attach onclick event to content links pointing to other tabs
    $('.tabs_container .content a[href*="#"]').each(function(){
		var linkHash = $(this).attr('href').split('#')[1];
		if ($.inArray(linkHash,tabList) != -1) {
	      	$(this).on('click', function(){
				Tabs.GoTo(linkHash, false)
			});
	    }
	});
  }
};

// Hook up the ready event to the tab initialization function
$(document).ready(function () { Tabs.Init(); });

With only a little creative CSS, we can have hover and active states that make it very clear to the user where they are, and where they can go. Included in the style is a fun little CSS-only arrow element. Check out the styles:

.tabs_container ul.toc {
    list-style: none;
    margin: 0;
    padding: 0;
}

.tabs_container ul.toc li {
    float: left;
    margin: 7px 4px 2px 0 !important;
	list-style-type: none !important;
	border:none;
}

.tabs_container ul.toc li a {
	display: block;
	background-color: #293A70;
	color: #fff;
	text-decoration: none;
	white-space: nowrap;
	text-align: center;
	padding: 3px;
	border: 2px solid #ccc;
	position: relative;
}

.tabs_container ul.toc li a:selected,
.tabs_container ul.toc li a:visited { outline: none; }

.tabs_container ul.toc li.current a {
    background-color: #B23428;
    color: #fff;
	padding:2px;
}

.tabs_container ul.toc li a span {
    display: block;
	font-weight: bold;
	line-height: 1em;
	white-space: nowrap;
	padding-right: 0px;
}

.tabs_container div.content {
 	padding: 5px 7px 0px 7px;
	clear: both;
}

/* arrows (no IE < 8) */
.tabs_container ul.toc li.current a, .tabs_container ul.toc li a:hover {
	background-color: #fff;
	color: #293A70;
	border: 2px solid #293A70;
	padding: 3px;
}

.tabs_container ul.toc li.current a:after, .tabs_container ul.toc a:before {
	top: 100%;
	border: solid transparent;
	content: " ";
	height: 0;
	width: 0;
	position: absolute;
	pointer-events: none;
}

.tabs_container ul.toc li.current a:after {
	border-color: rgba(136, 183, 213, 0);
	border-top-color: #fff;
	border-width: 10px;
	left: 50%;
	margin-left: -10px;
}

.tabs_container ul.toc li.current a:before {
	border-color: rgba(194, 225, 245, 0);
	border-top-color: #293A70;
	border-width: 13px;
	left: 50%;
	margin-left: -13px;
}

That's it! It'll load quick, change quick, and have a nice, smooth UX. Check out the live example:

Live Example

Remember, you can link to specific tabs directly using a URL hash:

Live Example w/ Hash

Or, you can just download it in a ZIP:

Download

4 comments

  1. Pretty good post. I have just stumbled upon your blog and enjoyed reading your blog posts very much. I am looking for new posts to get more precious info. Big thanks for the useful info.

Leave a Reply to Lance Dago Cancel reply

Your email address will not be published. Required fields are marked *