Friday, March 16th, 2007

Unobtrusive Control Tabs

Category: JavaScript, Library, Prototype, Showcase, Unobtrusive JS

Ryan Johnson has created unobtrusive JavaScript tabs called Control Tabs.

The project uses Prototype / Scriptaculous. You create the tabs using standard
anchors and named elements, so it’s completely accessible to non JS


  1. <script>
  2.     Event.observe(window,'load',function(){
  3.         $$('.tabs').each(function(tabs){
  4.             new Control.Tabs(tabs);
  5.         });
  6.     });
  7. </script>  
  9. <ul class="tabs">
  10.     <li><a href="#one">One</a></li>
  11.     <li><a href="#two">Two</a></li>
  12. </ul>
  14. <div name="one">
  15.     <p>I am tab one. I belong to group one.</p>
  16. </div>
  18. <div name="two">
  19.     <p>I am tab two. I belong to group one.</p>
  20. </div>
  22. <ul class="tabs">
  23.     <li><a href="#three">Three</a></li>
  24.     <li><a href="#four">Four</a></li>
  25. </ul>
  27. <div name="three">
  28.     <p>I am tab three. I belong to group two.</p>
  29. </div>
  31. <div name="four">
  32.    <p>I am tab four. I belong to group two.</p>
  33. </div>

Full Usage


  1. //with all available options. these are the defaults
  2. tabs = new Control.Tabs($('my_list_of_tabs'),{
  3.     linkSelector: 'li a', //(CSS selector) anchors inside list items is the default
  4.     activeClassName: 'active', //when a link is clicked this class name is added
  5.     beforeChange: function(control_tabs_instance,old_container){
  6.         //this is called after the link is clicked but before the tabs have changed
  7.     },
  8.     afterChange: function(control_tabs_instance,new_container){
  9.         //this is called after the link is clicked and after the tabs have changed
  10.     }
  11. });
  13. //to programatically set the active tab
  14. tabs.setActiveTab($('link_object'));
  15. //or by the link name (not id!)
  16. tabs.setActiveTab('one');
  18. //this property has a reference to the container that is being displayed
  19. active_container = tabs.activeContainer;
  20. active_container.update('some new HTML');

Control Tabs

Posted by Dion Almaer at 4:15 am

4.1 rating from 43 votes


Comments feed TrackBack URI

This is some nice code. But I think I will stick with Fabtabulous for a while longer, its just a little bit nicer I think.

Still a nice snippet.

Comment by Philip Plante — March 16, 2007

Accessible, unobtrusive JavaScript tabs with jQuery:

Comment by — March 16, 2007

Proto/Scriptac for unobtrusive tabs, isn’t that a bit overwhelming – re-inventing the wheel in the worst way. Just use DOMTab which is the best and the fastest solution here. Cheers

Comment by Oskar Krawczyk — March 16, 2007

Not very unobstrusive … linking with hash (#segment) points to an element-id in xhtml, not the element-name.

Anyways, scriptaculous is not needed, like written here, its just prototype.

Greetz, a moo-guy

Comment by digitarald — March 16, 2007

People who say ‘isnt scriptaculous + whatever’ a bit much for tabs, don’t understand you can build full web apps with these frameworks. If your page only had a tab and nothing else, then the framework wouldn’t be justified, but come on.

Comment by annoyed — March 16, 2007

It doesnt point at an id it points at a name and a class for the overall tabs_example div … you can change the css from #tabs_example to .tabs_example and use class=”tabs_example” instead of using #tabs_example {} and id|name=”tabs_example” this saves having to load relevent css styles for each element if you are usung a for / while / foreach loop to create the tabs and divs..
this is why i find it eacier than the other tabs systems that are available .. within a few minutes i managed to present multiple tabbed data.

Comment by Jester — March 16, 2007

Sorry meant to add code for example:

/* style /*
.tabs_example ul.tabs {

.tabs_example ul.tabs li {

.tabs_example ul.tabs li a {
padding:0 3px 0 3px;

.tabs_example ul.tabs li a:hover {

.tabs_example ul.tabs li {

.tabs_example div {




Content for 1

Content for 3

Content for 3

Or something to that effect


Comment by Jester — March 16, 2007

Negate that .. the code tags didnt work as i expected them to !!


Comment by Jester — March 16, 2007

Jester: I’m actually doing a vacancies (holidays) application right now for the business and I’m interested in seeing what you’ve done. Do you have a pointer of a demo for your app? I don’t need to have the code, I’m looking for ideas on how to implement it visually.

Comment by Eduo — March 16, 2007

Jester: Forget it. I just realized you were doing a system to track vacant positions, not vacations (holidays). My mistake.

Comment by Eduo — March 16, 2007


its all the same thing , its only database data or any other info …

I just through this together earlier .. your welcome to use it as a reference point


Comment by Jester — March 16, 2007

Jester: Thanks. I saw it already. It doesn’t have much to do with what I need (which is a combination of calendar/scheduler/task manager)

Comment by Eduo — March 16, 2007

Eduo: its pretty simple to do what you are trying to do …

Check out

That can be modded to anything you want


Comment by Jester — March 16, 2007

I’m the author, and just wanted to make a couple of notes. This script doesn’t require scriptaculous, just prototype. I also aggree this script would definitely be a lot lighter weight if it didn’t require Prototype. But part of the reason it is so easy to write a script like this is because they have done the hard work with things like iterators and getElementsBySelector. If anyone writes a port of this for jQuery or Moo tools, I will definitely put a link on the page.

Comment by Ryan Johnson — March 16, 2007

div elements do not have a name attribute in (X)HTML. Thus the proposed HTML is a. invalid and b. will not degrade gracefully, because a hash in an anchor href refers to an id, e.g. a fragment, not a name. The link is just not guaranteed to work without JavaScript. The name attribute will work for anchors only, but its deprecated anyway.

Comment by Klaus Hartl — March 16, 2007

Klaus, thanks. I’m a little surprised I did not know that, but you are quite right! I’ve updated the script and examples to use ids instead of names. Thanks for the feedback.

Comment by Ryan Johnson — March 17, 2007

Leave a comment

You must be logged in to post a comment.