Organic Tabs
Have you ever seen a tabbed content area in a sidebar that was a little “jerky”? The jerkiness can be caused by a bunch of things, like the content in the tabbed areas are of different heights, or maybe the way the switch happens the current one is hidden for a brief second before the new one shows up and the content below it jumps up and back down quickly. For lack of a better term, I’m calling tabs that behave more smoothly organic tabs .
The Plan
The plan is to build a tabbed area, something pretty simple to do from scratch with jQuery, and then make it behave better. Of course, we’ll keep it simple, and keep the markup clean and semantic. The guts of the functionality will be based on calculating heights and animating between those heights on the fly.

The HTML
We have a wrapper, then one unordered list for the tabs themselves. These tabs have rel attributes equal to the ID’s of the unordered lists below that they relate to. The content is the unordered lists inside the ‘all-list-wrap” div container. That’s the key here, the content wrapper.
<div id="organic-tabs">
<ul id="explore-nav">
<li id="ex-featured"><a rel="featured" href="#" class="current">Featured</a></li>
<li id="ex-core"><a rel="core" href="#">Core</a></li>
<li id="ex-jquery"><a rel="jquerytuts" href="#">jQuery</a></li>
<li id="ex-classics" class="last"><a rel="classics" href="#">Classics</a></li>
</ul>
<div id="all-list-wrap">
<ul id="featured">
<li><a href="#">Full Page Background Images</a></li>
<li><a href="#">Designing for WordPress</a></li>
<!-- More... -->
</ul>
<ul id="core">
<li><a href="#">The VERY Basics of HTML & CSS</a></li>
<li><a href="#">Classes and IDs</a></li>
<!-- More... -->
</ul>
<ul id="jquerytuts">
<li><a href="#">Anything Slider jQuery Plugin</a></li>
<li><a href="#">Moving Boxes</a></li>
<!-- More... -->
</ul>
<ul id="classics">
<li><a href="#">Top Designers CSS Wishlist</a></li>
<li><a href="#">What Beautiful HTML Code Looks Like</a></li>
<!-- More... -->
</ul>
</div> <!-- END List Wrap -->
</div> <!-- END Organic Tabs -->
The CSS
There isn’t much trickery here, just setting things up the look right.
ul { list-style: none; }
ul li a { display: block; border-bottom: 1px solid #666; padding: 4px; color: #666; }
ul li a:hover { background: #fe4902; color: white; }
ul li:last-child a { border: none; }
#organic-tabs { background: #eee; padding: 10px; margin: 0 0 15px 0; -moz-box-shadow: 0 0 5px #666; -webkit-box-shadow: 0 0 5px #666; }
#explore-nav { overflow: hidden; margin: 0 0 10px 0; }
#explore-nav li { width: 97px; float: left; margin: 0 10px 0 0; }
#explore-nav li.last { margin-right: 0; }
#explore-nav li a { display: block; padding: 5px; background: #959290; color: white; font-size: 10px; text-align: center; border: 0; }
#explore-nav li a:hover { background-color: #111; }
#jquerytuts, #core, #classics { display: none; }
#explore-nav li#ex-featured a.current, ul#featured li a:hover { background-color: #0575f4; color: white; }
#explore-nav li#ex-core a.current, ul#core li a:hover { background-color: #d30000; color: white; }
#explore-nav li#ex-jquery a.current, ul#jquerytuts li a:hover { background-color: #8d01b0; color: white; }
#explore-nav li#ex-classics a.current, ul#classics li a:hover { background-color: #FE4902; color: white; }
Few things possibly of interest. First, I’ve been liking this style of CSS formatting lately. Just single line format with single spacing between everything. No fancy tabbing. I realized recently I can read this just fine, I can write it faster, and not waste time formatting CSS to look pretty when this reads just as well. Second, there are a couple of tricks in here I use pretty frequently. The .last selector removes right margin on the tabs, so I can get that right tab flush right. The :last-child selector removes the border from the bottom list items, so we can get lines between each link but not before the first item or after the last.
The jQuery
The plan in plain English:
- Set the outer wrapper to a set height of the current content
- When a tab is clicked…
- Setting highlighting of tab to correct tab
- Fade out current content
- Fade in current content
- Animate height of outer wrapper to height of new content
$(function() {
$("#explore-nav li a").click(function() {
// Figure out current list via CSS class
var curList = $("#explore-nav li a.current").attr("rel");
// List moving to
var $newList = $(this);
// Set outer wrapper height to height of current inner list
var curListHeight = $("#all-list-wrap").height();
$("#all-list-wrap").height(curListHeight);
// Remove highlighting - Add to just-clicked tab
$("#explore-nav li a").removeClass("current");
$newList.addClass("current");
// Figure out ID of new list
var listID = $newList.attr("rel");
if (listID != curList) {
// Fade out current list
$("#"+curList).fadeOut(300, function() {
// Fade in new list on callback
$("#"+listID).fadeIn();
// Adjust outer wrapper to fit new list snuggly
var newHeight = $("#"+listID).height();
$("#all-list-wrap").animate({
height: newHeight
});
});
}
// Don't behave like a regular link
return false;
});
});
The code is commented up to hopefully explain things line by line. Normally we would never set the height on an outer wrapper of content. It’s kinda bad form, because content can change and height needs to be flexible to accommodate. But because we are calculating height dynamically each time anything happens with this list, we are somewhat safe. That is really the key here. Because the outer wrapper doesn’t change width until all the content swapping is done, the list adjusts very organically.
Enjoy!
Nice tutorial!
Great Article! Simple and elegant. The smoothness of it gives it a polished off look.
Thanks again
Very nice jQuery-Tutorial Chris!
This is an awesome piece of work you got !
Simple but very nice ! Makes it look really good .
Digg:
Digg This!
Retweet (fixed):
Retweet Me
PS: Chris: You should really get some social buttons on these posts :P
Thanks, but I dislike social buttons. I don’t feel like going off on a big thing about it right now though.
Sounds like an article to me ;)
LOL… you are such a purist :)
It’s great to read that you don’t like the social buttons. They’re such a mess. Remember when articles were about the content, and not about spreading it around everywhere? Things like that should be organic, imho.
thanks for the tut!!!!!!
nice tut. I’ve been using DOMtabs and I never really did care for them too much as it seemed like a pain to style properly.
This, on the other hand, seems great. Will be using it in a project I’m designing for a client today actually. THANKS :)
Looks great. The effect is too slow though.
Shmooove.
Question, is there any possibility to navigate to the tab from outside ul, let’s say having a link which will open the page on 3rd tab directly.
Everytime I will be searching for themes with tabs as it provides more content in less space. If I have known this earlier I have made one. Thanks I will include it in my theme myselves hereafter
Thanks, great tut! Super useful for wordpress sidebars…
I was just looking for a nice side tab code actually, might give this one a go, looks easy enough to edit and works really nice.
How hard would it be to incorporate a drop down into some of the list items? Im only just learning jQuery and would probably end up with something really messed up if I tried!
Very cool :-)
Could this be placed in a WP Page or Article?
Really beautiful! Very much enjoy your posts!
Quick question: How is jquery with seo? Meaning, the hidden columns, can a crawler-bot pic them up?
This is really creative..!
nice, but if javascript is disabled it is not very useful
second thing I noticed is when you click on two tabs fast (if you don’t wait for animation to finish) you’ll get two tabs open and it is a mess
Brilliant! Thanks a lot bro. I’m going to play w/ it tonight. Tee-hee. ;-)
Many thanks for the tutorial! I was just looking at your “Explore” section the other day trying to figure out how you did this. I was trying (and failing miserably) at building this myself.
I must say, I’m a little slow when it comes to understanding the jQuery. A little more explanation would be super useful… especially in a subsequent screencast!
cheers,
Jacob
Not a clone of this tutorial, but last month i’ve built and use a similar tab system for my portfolio’s mobile version at http://bcinarli.com/mobile, inspired from page height movement at css-tricks mobile version (http://css-tricks.com/i)
Really really nice and usefull tutorial.. a fantastic way to don’t create “jerky” tabs =)
I think I’ll remember this :D
Perfect timing, was about to start dealing fixing this exact issue with one of my projects!
Good. Thanks for share.
Chris, this is a really great tutorial and I’m always impressed about your creativity.
Thx, Michael
Chris, I am confused by your code, or in partcular your comment, i.e.
// Set outer wrapper height to height of current inner listvar curListHeight = $("#all-list-wrap").height();$("#all-list-wrap").height(curListHeight);To me the code above isn’t doing anything, surely it should be…
var curListHeight = $("ul#"+curList).height();$("#all-list-wrap").height(curListHeight);Also do you really need to collect height, as the animate will change the height of the div to the new ul height. Maybe it is just me, not understanding the code correctly. Nice effect though..
I know that seems weird, but what is happening there is that a height is literally SET on the outer wrapper. That way when the inside content changes, and say it’s taller, the wrapper wont “jerk” abruptly larger because it has a set height on it preventing it from doing that.
Ahh… right, that makes more sense, force the height of the div so that it will perform the height animation from a guaranteed starting point. Thanks Chris..
Chris,
I like the look of this. Is there a way to get some functionality for people who have javascript turned off?
Oh wow. That is nice. I am definitely going to find a use for this. I had been avoiding something like that because I thought it was so jerky before.
I’m also using the Anything Slider which is awesome.
Thanks!
awsome! going to check it right away!
Very nice solution!
thank’s chris for the nice tut.
what about tabs in witch the content takes the same color as the selected tab ,what’s the trick in this plz??
Great article as always chris
Nicely done Chris but…
I would like to see a stop() on the previously animation when you click on a new tab, test to click fast between the tabs and you will see that it bugs out (tested in FF 3.5.4 mac os). And the possibility do deep link to a tab by a hash (e.g. #tabOne) would have been nice. Otherwise it looks good I think!
Cool approach, as usual. I know you like your “rel” attributes, but I’m wondering why you didn’t just use the “href” attribute to point to the individual lists from the nav links? Doing so would provide three benefits:
1) Users without JavaScript would still be able to use the navigation links (clicking them would scroll the page to the appropriate list). This is the essence of progressive enhancement (and graceful degradation).
2) You wouldn’t have to prepend the hash mark at various places in your code–you’d already have it from the href attribute value.
3) You wouldn’t be using the rel attribute in a non-standard way (I know, not much of a gain, but…).
Am I missing something?
Yep, that’s absolutely how you should do it. In this case the rel thing is kinda dumb. I think it was a relic of the original version I used somewhere were ID’s were not going to be a possibility for whatever reason.
Really nice job but is there any way to make these tabs still work with js turned off.
This is really a nice little tut, will definitly use in an upcoming project. Thank you!
congrats! really cool. (= im trying to adapt to use 2 divs inside of the animation, one at time.
Hey,
Great stuff !
Just wondering…
Did anyone made any testing of this in IE 6 and 7 ?
Hey, i loved it!!!
Can you help me making this work from an outside menu??
Thanks!!!
great article.
Can you explain how can use it for blogger.
Thx…
Thanks for the article, Chris.
This was definitely food for thought for the current site I’m making.
@John Pisello, good call on using the href attribute instead of using rel. That graceful degredation can be everything to some of our clients!
Could this code be reusable?
I have many tabs so i don’t want to creaty to many functions for same thing
Thanks in advance