http://stilbuero.de Klaus Hartl – Stilbüro - Klaus Hartl


Jump to: Search, Additional Information.


Tabs plugin revised

I have revised the jQuery tabs plugin, so that it conforms to the jQuery plugin construct. To create the tab interface you now have to call the tabs function in a jquerish manner:

$('#container').tabs();

Therefore one can use jQuery’s powerful capabilities to retrieve the element holding the underlying HTML (good!) and of course chain methods (good!):

$('body>div:eq(1)').tabs().fadeIn('slow');

Other Changes

To provide some additional options the tabs function can take an optional argument which has to be an object literal. To activate a certain tab you have to write:

$('#container').tabs({on: 2}); // second tab is on

To further improve accessibility the plugin now uses classes instead of the hide/show functions (these do apply inline styles) for hiding inactive tab content. The content is then still visible in other media types then screen, e.g. print. This was reported on the jQuery mailing list.

Thus one must include the following rule in a style sheet:

@media projection, screen {
    .tabs-hide {
        display: none;
    }
}

In case you wonder: projection is aimed at Opera in full screen mode.

Next Steps

I will add more possible options. These came to my mind so far:

  • adjustHeight: true

    The height of each tab’s content will be adjusted to the largest one,
    so that you do not get annoying changes of the viewport height when switching tabs. This can be a bit irritating.

  • fade: 'speed'

    The plugin will use fadeIn/fadeOut for switching the tab content with the given speed.

  • slide: 'speed'

    Same as above, but the slideDown/slideUp functions are used for switching.

  • Both effects may be combined as well.

Here is the JavaScript source:

// tabs - jQuery plugin for accessible, unobtrusive tabs by Klaus Hartl
// v 1.0
// http://stilbuero.de/tabs/
// Free beer and free speech. Enjoy!
$.fn.tabs = function(options) {
    // basic stuff
    var ON_CLASS = 'on';
    var OFF_CLASS = 'tabs-hide';
    // options
    var on = options && options.on && (typeof options.on == 'number' && options.on > 0) ? options.on - 1 : 0;
    return this.each(function() {
        $(this).find('>div').not(':eq(' + on + ')').addClass(OFF_CLASS);
        $(this).find('>ul>li:eq(' + on + ')').addClass(ON_CLASS);
        var container = this;
        $(this).find('>ul>li>a').click(function() {
            if (!$(this.parentNode).is('.' + ON_CLASS)) {
                var re = /([_\\-\\w]+$)/i;
                var target = $('#' + re.exec(this.href)[1]);
                if (target.size() > 0) {
                    $(container).find('>div:visible').addClass(OFF_CLASS);
                    target.removeClass(OFF_CLASS);
                    $(container).find('>ul>li').removeClass(ON_CLASS);
                    $(this.parentNode).addClass(ON_CLASS);
                } else {
                    alert('There is no such container.');
                }
            }
            return false;
        });
    });
};

The sample moved here (download zipped files).

57 Comments

Comments feed

  1. [...] Important note: I have revised the tabs plugin and made some important changes. See here for the updated version. [...]

    Pingback by Klaus Hartl - Stilbüro : Accessible, unobtrusive JavaScript tabs with jQuery, June 18th, 2006 at 7:05 pm

  2. Great script!

    Could you call another php page to be the content of the tabs?

    Comment by cdnnick, June 20th, 2006 at 4:58 am

  3. Author Comment

    You could of course use jQuery’s load function to retrieve the tab content via remote call, like:
    $(container).find('>div').load('/path/to/your.php');

    In this case though the tabs could not be called accessible any longer.

    You wouldn’t need one div for each tab’s content, instead just one to hold the content and each time you click on a tab that content is simply updated via AJAX.

    Comment by Klaus, June 20th, 2006 at 7:59 pm

  4. How do you use the options? Thanks in advance.

    Comment by Jökull Sólberg Auðunsson, June 21st, 2006 at 12:19 pm

  5. [...] Also found a tab implementation that should prove very useful for what I’m working on right now (with a little modification to match my somewhat different HTML – I need a few more elements to hang my fancy backgrounds on). [...]

    Pingback by Jennifer Grucza » Archive » jQuery makes Javascript fun, June 22nd, 2006 at 2:01 am

  6. Author Comment

    All of the options go into one object literal, which is passed to the tabs function, like:
    $('#container').tabs({adjustHeight: true, fade: 'medium', slide: 'medium'});

    Please be advised that I’m still working on these options except for the one that highlights a certain tab, so please be a little patient.

    Comment by Klaus, June 22nd, 2006 at 2:27 pm

  7. I made a small modification to my copy of the tab javascript to be a little more bookmark-friendly:

    below this line: return this.each(function() {:

    var re = /([_\-\w]+$)/i;
    var reResult = re.exec(document.location);
    var on = 0;
    if (reResult != null) {
    var selectedTabId = reResult[1];
    var tabBodyElements = $(this).find('>.tabBody').get();
    for (var i = 0; i

    and below this line: $(this).find('.tabs>ul>li>a').click(function() {:

    var tabId = re.exec(this.href)[1];
    var target = $('#' + tabId);
    if (target.size() > 0) {
    document.location.hash = '#' + tabId;

    (Sorry my tab HTML is different, so my selectors aren’t quite the same as yours.)

    Comment by Jennifer Grucza, June 28th, 2006 at 10:31 pm

  8. Author Comment

    Jennifer,

    I have already implemented a solution (yet not posted apart from the jQuery mailing list) that lets you activate a tab via hash in the URL (Tabs 1.1). It also prevents the browser from jumping to the specified fragment in the document. I think it is quite similiar to your code.

    Try it out and get the source from there:
    http://stilbuero.de/jquery/tabs/#section-3

    Comment by Klaus, June 28th, 2006 at 11:00 pm

  9. Thanks for the great work. Esp. the bookmarkable update. I am using it with an ASP.NET 2.0 app. I have vertical tabs and an atlas panel on each tab content div. It is a data heavy page so it takes a while to load (or maybe it is just .NET). so I added a ‘loading…’ status div like it is a content div. I set all the other content DIVs to have the ‘tabs-hide’ class. This makes it so that when the page is done loading, the document ready function fires to hide the loading status div. I added:
    $(this).find('#' + hashId + ':hidden').removeClass(OFF_CLASS); /*Show the tab contents*/
    inside the block:

    if (location.hash)
    {
    ...
    }

    I haven’t gotten to the point of complete understanding of the code so I am having trouble finding out how I can remove the OFF_CLASS when there are no anchors given in the URL. Where or how would I do this?
    Again, thanks.

    Comment by DrydenMaker, July 7th, 2006 at 12:17 am

  10. love the plugin. one question though: can tabs be nested?

    Comment by Lukas, July 31st, 2006 at 3:38 pm

  11. Author Comment

    Lukas, yes they can, here’s a quick test.

    Comment by Klaus, August 1st, 2006 at 10:58 am

  12. The method you describe above for fadeIn using jquery’s library doesn’t work for me. Could you provide a more complete code example?

    I’m refering to this:

    $('body>div:eq(1)').tabs().fadeIn('slow');

    Comment by Harvey Ramer, August 3rd, 2006 at 5:26 am

  13. Author Comment

    Harvey, the code you are refering to would fade in the whole element that contains all the tabs.

    I think you want to have a fade effect when switching the tabs? I’ve updated the demo page with an example that has that fading. It works but only with the latest SVN version of jQuery and the tabs are not accessible anymore in other media types than screen.

    I am still waiting for a stable release of jQuery 1.0 to fully implement the effects I wrote about.

    Comment by Klaus, August 3rd, 2006 at 1:29 pm

  14. Great work!
    Just a quick note, slide/fade bugs under FireFox (known issue of JQuery) but even with latest svn build I could not make it work, can you check it out ?
    Cheers!

    Comment by gib, August 6th, 2006 at 11:44 pm

  15. another thing: your code does not seem to be packable with : http://dean.edwards.name/packer/
    cheers!

    Comment by gib, August 7th, 2006 at 12:45 am

  16. Hi all,
    I’m fairly new to javascript, so I probably won’t understand the technical jargon you guys might reply with to my question, so go easy on me :) Here goes:
    Is there any way to prevent the code from defaulting to the first tab when you refresh your browser? I happen to have quite a few forms in each of the tabs, and would like the page to stay on the specific tab when pressing the submit or refrsh button.
    Thanx in advance
    Nicolas

    Comment by Nicolas, August 16th, 2006 at 8:46 am

  17. Author Comment

    Nicolas, you can do this quite easily. Call your page with an URL containing a hash that references one of the tabs:

    /path/to/your/page.html#activetab

    Same with forms: Just add the hash to to action attribute:

    <form action="#activetab">

    That way the tab is always highlighted (and is even bookmarkable). I wrote about that in another post. Hope this helps!

    Comment by Klaus, August 17th, 2006 at 9:43 pm

  18. Klaus, loving the plug-in. Noticed a small issue; the zip you supply assumes that the user keeps the jQuery js file locally (but doesn’t supply the file), as opposed to fetching it from the central server (as the previous version did).

    Perhaps changing it back would save someone else 10 minutes of head-scratching.

    Comment by Original Sin, August 18th, 2006 at 8:30 pm

  19. [...] Tabs per semplificare la creazione interfaccie a pannelli [...]

    Pingback by jQuery: più lo uso e più mi piace   |   .:: Maurizio Pelizzone ::., August 21st, 2006 at 1:01 pm

  20. I figured out my hash problem posted earler.
    First I change:
    return false;
    to
    return true;
    This causes the anchor to insert into the URL.
    Next I insert:

    if (!location.hash)
    {
    /*Show the defalut contents*/
    $(this).find('>div:eq(0)').removeClass(OFF_CLASS);
    }
    else
    {
    /*Show the tab contents*/
    $(this).find('#' + hashId + ':hidden').removeClass(OFF_CLASS);
    }

    at the end of the return this.each(function() block.
    This gives you bookmarkable tabs.

    Comment by DrydenMaker, August 21st, 2006 at 10:37 pm

  21. Great plugin.

    However, I couldn’t get it working with the compressed version of jQuery 1.0.1

    Any ideas?

    Comment by Neil, September 1st, 2006 at 3:57 pm

  22. Author Comment

    Neil, there was a bug in jQuery 1.01 which is fixed now. Just try it out… slide effect is fixed as well.

    The jQuery library is also included in the zipped download file, so no more head scratching.

    Comment by Klaus, September 1st, 2006 at 5:45 pm

  23. I noticed an issue with the plugin that i’m having when i set it up as well. On the section with just the slide, it appears that the content is actually sliding outside of the containing div. On my version i could only solve this problem by setting the class .fragment to have a specified height, and attempting to use height: 100% was no help. any ideas on how to make sure the div height matches the content?

    Comment by Kit Churchill, September 12th, 2006 at 5:00 pm

  24. Is it possible to remember the last tab it been activated?
    Something like a cookie to remember the last tab when u go to next page.

    Like a site wide persistence stuff.

    Comment by Eric, September 15th, 2006 at 7:57 am

  25. Author Comment

    Eric, that would be possible, sure. But this is not implemented (yet). Cookie functionality would add a lot of code, but I’m working on a cookie plugin for jQuery anyway.

    Comment by Klaus, September 16th, 2006 at 7:09 pm

  26. Hey Kalus,
    I’m just rebuilding my website and I’m using your template together with jQuery. its great, though its hard work for me.
    I love the fact that the tabs know to stay on the right tab (.on), I wanted to implement it in my main tab bar, which is linking between different html pages. The message that comes up is “there is no such container”. Is there a way to fool the code and to redirect it another html?

    The website listed above is the page that I’m working on.

    Comment by Zohar, September 21st, 2006 at 3:21 am

  27. Zohar,

    Can you perhaps use iFraming, or AJAX (as suggested earlier)? Wouldn’t be difficult to implement either way.

    –Adrienne

    Comment by Adrienne Travis, October 6th, 2006 at 3:17 pm

  28. hi klaus,
    great solution. i just made my first tests. it works fine.
    but is there a way to have the anchor list in some other place than inside the same container-1 div along with the sections?
    cant get it working outside of the container-1 div…

    Comment by marc, October 7th, 2006 at 11:57 pm

  29. Author Comment

    Hi Marc,

    I’m sorry, the plugin is not designed to work like that.

    Comment by Klaus, October 8th, 2006 at 4:52 pm

  30. oh no :-(
    it was sooo close.
    as you can see, i only have one more div, its wrapped around the container-1.
    unfortunaly i can’t get rid of it. in my case its structural important.
    do you see any chance to stretch the code for another div?

    Section 1
    Section 2
    Section 3

    Section 1
    text
    text

    Section 2
    text
    text

    Section 3
    text
    text

    Comment by marc, October 8th, 2006 at 6:31 pm

  31. hi klaus,
    after days of testing i’m quite happy witht the results. there are some safari issues with animations like fade on absolute positioned divs, but thats ok.
    but there is one thing i can’t get to work.
    i try to include a complete container with its li-navi and its divs via .load event. but when i switch tabs, they have lost their dom connections and just dont work. any idea if including the complete tab content is possible?

    Comment by marc, October 17th, 2006 at 7:36 pm

  32. Author Comment

    Marc, I really cannot tell from your description. Do have a (test) page where I can look at?

    Comment by Klaus, October 18th, 2006 at 12:05 am

  33. hi klaus,
    maybe its a more of a general problem. if i include an external html file via .load in some main file which contains all the scripts, the scripts wont recognize the dom elements (ids, classes) in the included file. if i put the scripts in the included file it works for the included html.
    maybe this is a limitation in jquery?
    i will look for a way to demo this…

    Comment by marc, October 18th, 2006 at 10:14 pm

  34. [...] Tabs [...]

    Pingback by Yorch » Blog Archive » Mejorar interfaces Web, October 20th, 2006 at 9:10 pm

  35. Hello Klaus. I love the plugin. Thank you for putting it out there.

    Just one problem.. Safari v.2.0.4 consistently crashes when it uses the slide animation in a very specific situation.

    I have a column of links on the left side of the page that is absolutely positioned. There’s the containing div#col-l for the positioning then 2 more div’s as a direct child with one of them containing the tabs.

    div#col-l
    div#sidebar-1a -tabbed
    ul…
    blocks…
    div#sidebar-1b

    I’m using Drupal as my CMS so the sidebars 1a/1b come and go depending on the page being viewed. If both sidebars are present and the ’slide’ animation is used for the tab, Safari crashes. Tried disabling the animation and the crashing stops.

    The links on the upper left will trigger a crash but this one works fine.

    This is more of a heads up as I’ll try to find a workaround if it can’t be fixed soon.

    @Marc, you can use jQuery’s DOM manipulation to restructure to what’s needed. It’s what I had to do since Drupals block output is nothing like the required structure.

    BTW, I wrote how you can do this in Drupals Handbook page for any Drupal users out there.

    Comment by joon, October 22nd, 2006 at 5:52 pm

  36. Great plugin, very easy to use!
    But unfortunately, there seems to be a problem with Konqueror (I use version 3.5.5). I tried your demo page: clicking on one tab correctly swap to this one, but after that, it’s stuck. You can’t click on a tab more than once, subsequent clicks won’t let you go back to the previous tab, or to any other.

    Comment by kilian, October 25th, 2006 at 1:17 am

  37. Author Comment

    Kilian, thanks for the catch. I don’t have access to Konqueror at the moment, but I’m going to buy Parallels for my Mac soon, then I’m going to check that…

    Comment by Klaus, October 25th, 2006 at 11:01 am

  38. I am having a real hard time.

    I think a crash in IE6 is coming from tabs. I have tested everything else and that’s where I’m at currently.

    Basically, once the page loads, after about 10 seconds, if you try to click a tab IE just freezes up.

    Any input on this would be great.
    Demo here

    It works great in Safari and FF, only IE problems. I haven’t tested IE7 yet.
    Also, if you click on the tabs prior to that it seems to work fine for a time.

    I’m really stumped.

    Comment by Jeff Rader, October 29th, 2006 at 5:35 am

  39. Author Comment

    Are you sure it’s because of the tabs? Which version and which jQuery version are you using?

    Comment by Klaus, October 29th, 2006 at 2:49 pm

  40. I can’t say for certain that it is tabs, but that is what it seems to be.

    If I disable the tabs everything runs just fine.

    I just upgraded to jquery1.03 and tabs2.0 and got the same results.

    I have a large amount of js running, but I’ve been testing all of it and everything seems to check out.

    Comment by Jeff Rader, October 29th, 2006 at 8:48 pm

  41. OK, actually tabs 2.0 was causing the whole page to freeze. I went back to 1.1 and it only freezes now one I have gone through a few specific steps.

    If you are interesting in helping, I can outline the steps. Once I figure it out, I’ll see if I can get it working with 2.0 as well.

    Comment by Jeff Rader, October 30th, 2006 at 6:47 pm

  42. Author Comment

    Hi Jeff,

    I don’t have much time, but of course I’m still interested if it is caused by the tabs…

    Comment by Klaus, October 30th, 2006 at 10:36 pm

  43. I didn’t get 2.0 to work. I have jsut changed the workflow that was resulting the error. It didn’t really “fix” the problem, but the site works now.

    I wish I had more information, but it was really weird.

    Ah, well, hopefully it was just an IE6 bug and we can all forget about it soon :)

    Comment by Jeff Rader, November 1st, 2006 at 4:53 am

  44. Do I have to always use the exact combinations of class names? Since i have the same “selected” class scattered all over my site, I wanted to have the tab selected style use a different name, but I don’t know how to set them. Is there a way?

    Thanks!

    Comment by gsarwohadi, November 1st, 2006 at 1:34 pm

  45. Author Comment

    Gsarwohadi, you can specify a different class name as an option (Tabs 2.0):

    $('#container').tabs({
    selectedTabClass: 'whatever'
    });

    I’m working on documenting all the updates in Tabs 2.0 at the moment.

    Comment by Klaus, November 1st, 2006 at 10:56 pm

  46. Ah, great. Is the latest release version 2.0 already? Because I tried that attribute but doesn’t work..

    Cheers

    Comment by gsarwohadi, November 2nd, 2006 at 3:01 pm

  47. And btw, I’m really curious.. in your code it doesn’t state any ‘.selected’ in there. Where does it say that it will look for that particular class for hover/selection?

    Comment by gsarwohadi, November 2nd, 2006 at 3:03 pm

  48. Author Comment

    Yes the latest release is 2.0 and the demo already uses it. I’m going to announce that on my blog as soon as I’ve finished the documentation. The reason why you don’t find it in the code is obviously because I have removed all occurences and moved it to a variable to be able to make that configurable. But on line 113 there’s one occurence… ;-)

    Comment by Klaus, November 2nd, 2006 at 8:40 pm

  49. [...] Since the first release of my jQuery Tabs plugin I constantly worked on it – which is most notable if you take a look at the demo page – but until now I have never officially released a new version. Since I made a little API change recently and because I think the plugin is pretty mature now, I hereby announce version 2 of the jQuery Tabs plugin. I’m going to describe all changes and additions since version 1. [...]

    Pingback by Klaus Hartl - Stilbüro : Tabs Version 2, November 6th, 2006 at 11:20 am

  50. Author Comment

    Kilian, I fixed the issue in Konqueror.

    Comment by Klaus, December 6th, 2006 at 11:39 am

  51. Hi Klaus,

    I have actually the same problem than Jeff Rader, aka IE7 crashing in certain cases (not 100% CPU, but rather 50% on my machine… looks like a loop somewhere). I don’t know for sure, but this seems to happen when the tab contains many elements (like 1/2 FckEditor and a bunch of form fields).

    Working ok with Firefox.. i’ll check if this has anything to do with visual effects.

    Comment by Laurent Chardin, January 19th, 2007 at 8:16 pm

  52. Looks like my last bug was caused by a custom function i added (problem with FckEditor in hidden tabs)

    Works ok when i disable it.

    Comment by Laurent Chardin, January 21st, 2007 at 1:46 pm

  53. Hi Klaus,

    this is a great plugin! How do I activate the tabs onMouseover? I’m having some trouble getting it to work. Any thoughts?

    Comment by Rik Logtenberg, February 4th, 2007 at 2:47 am

  54. Hi, apologies I’m completely new to jquery, the tabs are superb and I am trying to use them in my current development.. however print displays the contents of the three tabs I am using.

    I only want to print the contents of the current tab and am having problems getting this to work.

    Kind Regards
    Phil

    Comment by phil, April 27th, 2007 at 9:51 am

  55. Hi Klaus, I have sorted the problem, I just needed to add print to the media types in jquery.tabs.css.

    Thanks again the tabs are brilliant!!

    Comment by phil, April 27th, 2007 at 9:57 am

  56. Hallo Klaus,
    How can I refresh a remote tab ?
    On my second tab I have some items, then I add a new item using modal window and when I close this modal window I’d like to refresh the tab that is active to display the item that I’ve added.
    Is that possible ?
    Thank you in advance.

    Comment by Alexandre, August 14th, 2007 at 4:21 am

  57. hello friend my English is not very good queria for asking to him since I do with the example of tab in jquery that you desarrolo to work it with a page with bellboys that remains in he himself tab because I have proven it and moves to the first tab him agradeceria by its aid

    Comment by alvaro montilla, September 27th, 2007 at 4:45 pm



Klaus Hartl – Stilbüro is powered by WordPress, jQuery, XHTML, CSS and me.