Access options:

New web site is in beta: websemantics.uk. A far better experience.

New version available: Accessible Tab Navigation (version 5)

Dramatically updated and revamped.
Version 4 is now deprecated, kept for archive reference only.

Accessible Tab Navigation (version 4)

author: mike foskett incept: 21st May 2010

last update: 18th March 2016

A progressively enhanced lightweight and accessible tab navigation which doesn't rely on jQuery.

Written to replace a jQuery method which wasn't accessible via the keyboard and didn't work without JavaScript. Originally written for the Tesco direct web site.

Version 4 updated to include multiple versions on one page and to allow hover, or focus, action to activate tabs.

Example

Tab One

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed tristique volutpat est, fermentum posuere ligula pretium egestas. Cras id justo nibh, at laoreet nisi. Quisque accumsan faucibus malesuada.

Tab Two

Pellentesque ut sem sapien. Integer vitae dui elit, eu interdum erat. Duis non velit sed leo convallis imperdiet. Etiam ullamcorper imperdiet nisi eu interdum. Phasellus accumsan laoreet accumsan.

Tab Three

Ut suscipit ultrices commodo. Aliquam erat volutpat. Aliquam erat volutpat. Aenean sed odio augue. Cras pellentesque accumsan ipsum, at molestie dolor malesuada laoreet. Suspendisse nec pharetra orci.

A complete commented bare bones demo version is available. As is a minified JavaScript [1.05 KB] version.

Caveat: This code will only produce a single tab navigation an a page. If you require more than one it means duplicating the JavaScript and changing the id's. Not the best solution but works. Live example with two separate tab navigations: Tesco mini-site for AMD. I may further this project to correctly accommodate multiples in the future. - Done in version 4.

The XHTML

Basically a list of anchor links which reference div blocks.


<ul id="tabableNav" class="hoverable">
  <li class="on"><a href="#tab1">Tab One</a></li>
  <li><a href="#tab2">Tab Two</a></li>
  <li><a href="#tab3">Tab Three</a></li>
</ul>

The class="on" distinguishes which tab is currently active.


<div>

  <div id="tab1" class="tabbed on">
    tab 1 content
  </div>

  <div id="tab2" class="tabbed">
    tab 2 content
  </div>

  <div id="tab3" class="tabbed">
    tab 3 content
  </div>

</div>

The class="tabbed" hides inactive tab blocks when JavaScript is present.

The class="on" displays which tab is currently active.

The scripting

The script is presented in a closure to prevent variables interfering elsewhere. It was also Linted as far as possible.


var accessibleTabs4 = (function () {

  var onClass;

  // author: Simon Willisons - http://simonwillison.net/2004/May/26/addLoadEvent/
  function addLoadEvent(f){var o=window.onload;if(typeof window.onload!=='function'){window.onload=f;}else{window.onload=function(){if(o){o();}f();};}}

  // A few of my standard set of functions
  function hasClass(o,c){return new RegExp('(\\s|^)'+c+'(\\s|$)').test(o.className);}
  function addClass(o,c){if(!hasClass(o,c)){o.className+=' '+c;}}
  function removeClass(o,c){if(hasClass(o,c)){o.className=o.className.replace(new RegExp('(\\s|^)'+c+'(\\s|$)'),' ').replace(/\s+/g,' ').replace(/^\s|\s$/,'');}}
  

The activateTab function is called whenever a tab is clicked, or optionally hovered / focused.


  function activateTab() {
    var j = this.linkset.length; // number of links in this tab set
    while (j--) { // go through each link in turn

      // remove the "on" class from both link and content div
      removeClass(this.linkset[j].parentNode, onClass);
      removeClass(this.linkset[j].tabId, onClass);
    }

    // Add the "on" class to both the active link and content div
    addClass(this.parentNode, onClass);
    addClass(this.tabId, onClass);
    return false;
  }
  

Initialisation waits until the page has loaded. Then works through each tab link and associates


  function init(cfg) {
    addLoadEvent(function () { // wait until page has fully loaded
      var tabNavId = document.getElementById(cfg.navId); // get the ul id from the function parameter
      onClass = cfg.onClass || "on"; // On class defaults to "on" but may be overwritten by a function parameter
      if (tabNavId) { // if id passed as a parameter exists
        var As = tabNavId.getElementsByTagName("a"), // get list of contained links as objects
          i = As.length,
          hoverable = hasClass(tabNavId, cfg.hoverableClass || "hoverable"); // check if hover / focus action is required
        while (i--) { // now with each link object
          As[i].tabId = document.getElementById(As[i].href.slice(As[i].href.lastIndexOf('#') + 1)) || false; // get the content id from the href or false if not available
          if (As[i].tabId) {
            As[i].linkset = As; // each link object stores a reference to each link in the list

            // add the action to each link
            As[i].onclick = activateTab;
            if (hoverable) {
              As[i].onmouseover = activateTab;
              As[i].onfocus = activateTab;
            }
          }
        }
      }
    });
  }

  return {init : init};

}());
  

// Call the function with the id of navigation tab ul as a parameter
// Optionally overwrite the default settings:
//     onClass : "on", hoverableClass : "hoverable" 

accessibleTabs4.init({navId : "tabableNav"});
  

The CSS

The styling requires JavaScript detection so it can act prior to page rendering. Indicated by the class "hasJS" added to the html element. This is achieved by adding a small script directly after the title element:


<script type="text/javascript">/*<![CDATA[*/document.documentElement.className="hasJS";/*]]>*/</script>

Styling required by the scripting only. Nothing cosmetic here:


.hasJS .tabbed {position:absolute; top:0; left:-200em;}
.hasJS .on {position:relative; top:0; left:0}

Any issues please email me or leave a comment below.

Have your say…

1

Kang Kapuk

23 10 2012

[ASK] how to disable of bundle css at blogger template...
this code is ..
&lt;link type=&#039;text/css&#039; rel=&#039;stylesheet&#039; href=&#039;//www.blogger.com/static/v1/widgets/1937454905-widget_css_bundle.css&#039; /&gt;
thank's

2

bjk

26 12 2013

thx

3

Summer

10 09 2015

I really like the information and resources I have found browsing the entire site. Hoping one day to be able to implement my favorite ones. I need to learn a bit more to do it but it's on my list!

Maybe a good time would be now that my 27" XPS all-in-one is in surgery getting a new motherboard. I have time to practice on this little laptop as it does not work well for updating my site (far too slow and small).

Say what?

Links currently disabled due to spam abuse.
Will reinstate at a later date using Ajax to remove any SEO benefits from posts.

Captcha number, inaccessible I know. If you're having difficulty please use the email link

The commenting system used here is a modified version of comment_rave. Capcha method by Hardcode NL.

Site search & complementary navigation:

Site search:

Online tools

Most popular

New to site