JavaScript Tabs - Create Tabbed Web Pages Easily

Learn how to use JavaScript to create a tabbed Web page for holding lots of content. Full code included for copying and pasting into your website!

This tutorial shows how to create a Web page containing JavaScript-driven tabs. Each tab displays a separate chunk of content when clicked — perfect if your page needs to hold a large amount of content. It's also great for things such as multi-step ("wizard"-style) Web forms.

Click the link below to see a tabbed page in action:

JavaScript tabs screenshot

The JavaScript and markup are coded in such a way that the page degrades gracefully in browsers that don't support JavaScript.

In this tutorial you learn how this tabbed page is put together. You can then use the code and ideas to build your own tabbed Web pages. Let's get started!

Creating the HTML for the tabbed page

The HTML for the tabs and content is very simple. You store each tab's content within a div element with a class of tabContent and a unique id for reference. Here's the first of the 3 tab content divs in the example:


<div class="tabContent" id="about">
  <h2>About JavaScript tabs</h2>
  <div>
    <p>JavaScript tabs partition your Web page content into tabbed sections. Only one section at a time is visible.</p>
    <p>The code is written in such a way that the page degrades gracefully in browsers that don't support JavaScript or CSS.</p>
  </div>
</div>

The tabs themselves are simply links within an unordered list:


<ul id="tabs">
  <li><a href="#about">About JavaScript tabs</a></li>
  <li><a href="#advantages">Advantages of tabs</a></li>
  <li><a href="#usage">Using tabs</a></li>
</ul>

Give the ul an id of "tabs" so that the JavaScript code can locate it. Each link within the list links to its corresponding content div by referencing the id of the div ("about", "advantages", or "usage"). Since these are standard HTML links, they work fine even without JavaScript.

You can add as many tabs as you like to the page. Simply add a new content div and give it a unique id, then add a link to it within the tabs list.

Creating the CSS

Some CSS is needed in order to make the tabs look like tabs (and make them nice to look at):


body { font-size: 80%; font-family: 'Lucida Grande', Verdana, Arial, Sans-Serif; }
ul#tabs { list-style-type: none; margin: 30px 0 0 0; padding: 0 0 0.3em 0; }
ul#tabs li { display: inline; }
ul#tabs li a { color: #42454a; background-color: #dedbde; border: 1px solid #c9c3ba; border-bottom: none; padding: 0.3em; text-decoration: none; }
ul#tabs li a:hover { background-color: #f1f0ee; }
ul#tabs li a.selected { color: #000; background-color: #f1f0ee; font-weight: bold; padding: 0.7em 0.3em 0.38em 0.3em; }
div.tabContent { border: 1px solid #c9c3ba; padding: 0.5em; background-color: #f1f0ee; }
div.tabContent.hide { display: none; }

These CSS rules work as follows:

body
This sets a nice font and font size for the page.
ul#tabs
Styles the tabs list, turning off bullet points.
ul#tabs li
The display: inline; property makes the tabs appear across the page.
ul#tabs li a
Styles the links within the list. Each link is given a border around every side except the bottom, so that the active tab blends nicely with its content div below.
ul#tabs li a:hover
Highlights a tab when hovered over with the mouse.
ul#tabs li a.selected
Styles a selected tab by giving it a lighter background and bold text, and making it bigger. Notice that the bottom padding is increased to 0.38em to make sure that the tab blends with the content div.
div.tabContent
Sets a style for the tab content areas so that they match the tab design.
div.tabContent.hide
Used to hide unselected tabs.

Creating the JavaScript code

Finally, of course, you need JavaScript to make the tabs work. Here's what the JavaScript needs to do:

  • Attach a showTab() onclick event handler to each of the tab links.
  • Hide all content divs except the first, so that only the leftmost tab's content is visible when the page loads.
  • When a tab is clicked, showTab() displays the current tab content, and hides all other tab content divs. It also highlights the clicked tab and dims the other tabs.

The JavaScript kicks off by creating two arrays to hold the tab link elements and the content divs:


    var tabLinks = new Array();
    var contentDivs = new Array();

Four functions control the tabs:

  • init() sets up the tabs.
  • showTab() displays a clicked tab's content and highlights the tab.
  • getFirstChildWithTagName() is a helper function that retrieves the first child of a given element that has a given tag name.
  • getHash() is another short helper function that takes a URL and returns the part of the URL that appears after the hash (#) symbol.

Here's how these functions work.

The init() function

The first, and most complex, function is init(). It's called when the page loads, thanks to the body element's onload event:


  <body onload="init()">

Here's the function itself:


    function init() {

      // Grab the tab links and content divs from the page
      var tabListItems = document.getElementById('tabs').childNodes;
      for ( var i = 0; i < tabListItems.length; i++ ) {
        if ( tabListItems[i].nodeName == "LI" ) {
          var tabLink = getFirstChildWithTagName( tabListItems[i], 'A' );
          var id = getHash( tabLink.getAttribute('href') );
          tabLinks[id] = tabLink;
          contentDivs[id] = document.getElementById( id );
        }
      }

      // Assign onclick events to the tab links, and
      // highlight the first tab
      var i = 0;

      for ( var id in tabLinks ) {
        tabLinks[id].onclick = showTab;
        tabLinks[id].onfocus = function() { this.blur() };
        if ( i == 0 ) tabLinks[id].className = 'selected';
        i++;
      }

      // Hide all content divs except the first
      var i = 0;

      for ( var id in contentDivs ) {
        if ( i != 0 ) contentDivs[id].className = 'tabContent hide';
        i++;
      }
    }

This function does 3 things:

  1. It loops through all the li elements in the tabs unordered list. For each li element, it calls the getFirstChildWithTagName() helper function to retrieve the a link element inside. Then it calls the getHash() helper function to extract the part of the link's URL after the hash; this is the ID of the corresponding content div. The link element is then stored by ID in the tabLinks array, and the content div is stored by ID in the contentDivs array.
  2. It assigns an onclick event handler function called showTab() to each tab link, and highlights the first tab by setting its CSS class to 'selected'.
  3. It hides all content divs except the first by setting each div's CSS class to 'tabContent hide'.

So that init() runs when the page loads, make sure you register it as the body element's onload event handler:


  <body onload="init()">

The showTab() function

showTab() is called whenever a tab link is clicked. It highlights the selected tab and shows the associated content div. It also dims all other tabs and hides all other content divs:


    function showTab() {
      var selectedId = getHash( this.getAttribute('href') );

      // Highlight the selected tab, and dim all others.
      // Also show the selected content div, and hide all others.
      for ( var id in contentDivs ) {
        if ( id == selectedId ) {
          tabLinks[id].className = 'selected';
          contentDivs[id].className = 'tabContent';
        } else {
          tabLinks[id].className = '';
          contentDivs[id].className = 'tabContent hide';
        }
      }

      // Stop the browser following the link
      return false;
    }

The function extracts the selected ID from the clicked link's href attribute and stores it in selectedId. It then loops through all the IDs. For the selected ID it highlights the corresponding tab and shows the content div; for all other IDs it dims the tab and hides the content div. It does all this by setting CSS classes on the tab links and content divs.

Finally the function returns false to prevent the browser from following the clicked link and adding the link to the browser history.

The getFirstChildWithTagName() function

This helper function returns the first child of a specified element that matches a specified tag name. init() calls this function to retrieve the a (link) element inside each list item in the tabs list.


    function getFirstChildWithTagName( element, tagName ) {
      for ( var i = 0; i < element.childNodes.length; i++ ) {
        if ( element.childNodes[i].nodeName == tagName ) return element.childNodes[i];
      }
    }

The function loops through the child nodes of element until it finds a node that matches tagName. It then returns the node.

Learn about the childNodes and nodeName properties in the article Looking inside DOM page elements.

The getHash() function

The getHash() helper function returns the portion of a URL after any hash symbol. Used by init() and showTab() to extract the content div ID referenced in a tab link.


    function getHash( url ) {
      var hashPos = url.lastIndexOf ( '#' );
      return url.substring( hashPos + 1 );
    }

Putting it together

That's all there is to creating JavaScript-enabled tabs! Take another look at the demo again, and view the page source to see how the HTML, CSS and JavaScript code appear in the page:

  • The CSS and JavaScript go inside the page's head element. (You can move these into separate .css and .js files and link to them, if you prefer.)
  • The page's body element contains the onload event handler to trigger the init() function.
  • The tabs ul element contains the tab links.
  • Each tab's content is stored in a div with a class of tabContent and a unique id (referenced in the corresponding tab link).

Feel free to use this code in your own Web pages. Happy tabbing!

Follow Elated

Related articles

Responses to this article

20 most recent responses (oldest first):

05-Mar-15 15:02
What would be the point??

Anything 'password protected' with javascript would require the password to be in the page source code, or require a round trip to the server.

Either that or the whole set up would require recoding using AJAX.
17-Nov-15 15:47
This code is great, the only problem I have is that when the page is displayed, it is only displaying 2 inches of the pages in the tabs with a scroll bar. I can't see anything in any of the scripting that specifies a page height.

Zeek
17-Nov-15 17:47
Change the tab height value in the style sheet.
18-Nov-15 07:50
Chris,

There was no height definition in my CSS. I saw that shochberg had height in his CSS at 60, so I added that to my CSS at 600, but it still is only a couple of inches. Here is the line I added it on.

div.tabContent { border: none; padding: 0.5em; color: #007777; background-color: #f6f6ce; height:600; }

[Edited by zeek69 on 18-Nov-15 07:50]
18-Nov-15 11:12
600 what?

To be applied correctly, a height value, along with all other dimensional properties require a valid dimension identifier, (%, px, em, pt etc). A value without that means the browser has to 'guess' what you mean.
What they then usually revert to, is the 'height' that would nominally be applied to inline level elements, ie; the height of the element content box, the padding and margins are then added to giver the overall 'box height', and as you are "including" an iframe with an external page, the 'content height' is therefore only made up from the iframe top and bottom margins, padding and border values, because the external document has no width or height that the CSS rendering engine can use.
27-Jan-16 14:20
This was very helpful, thanks! I'm sort of new to this, could somebody help me apply transitions between tabs when it shows content? Thanks.
28-Jan-16 03:40
The purpose of the tutorial is for you to learn how to modify it to suit what you want.

http://forum.jquery.com/topic/how-to-animate-content-between-tabs

Don't forget to come back and add your solution to this thread.
04-Feb-16 23:26
I seem to be having an issue with the script. I am new to web design and I can't identify the issue. I have copied the CSS portions as provided and have expanded the HTML portions so that I have six tabs. As soon as I go past six something happens so that the content for each tab is displayed on all of the tabs. Any suggestions?
05-Feb-16 08:56
" Any suggestions?"

None whatsoever.


Before anyone can offer the remotest possibility of useful 'suggestions' we need to SEE the problem!
08-Feb-16 21:45
Lesson learned. I found out what was wrong with my last question. I have several more questions.

First, when I resize my browser the ul elements get out of whack and no longer line up with the tabcontent elements. As you can see I have used vw to make the text size relative to the viewport, but I am not sure how or if can use it for margins and padding.

Second, I would like to make it so my tabs line up with the edges of the tabcontent elements. Meaning, if I have six tabs, I would like the left edge of the first tab to line up with the left edge of its associated tabcontent, and for the right edge of the last tab to line up with right edge of its associated tabcontent (all while making sure the interior tabs are all equally spaced).

Thanks!


ul#tabs {
list-style-type: none;
margin: 20px 40px 0 40px;
padding: 0 0 0.3em 0;
margin: 30px 0 0 0;
}
ul#tabs li {
display: inline;
}
ul#tabs li a {
color: red;
font-family: 'top_secretbold';
font-size: 135%;
font-size: 1.35vw;
font-weight: bold;
background-color: #ffeecc;
border: 1px solid;
border-color: #696969;
padding: 1vw 1vw .2vw 1vw;
text-decoration: none;
}
ul#tabs li a:hover {
background-color: #ffe5b3;
}
ul#tabs li a.selected {
color: #red;
background-color: #ffe5b3;
border-bottom: none;
font-weight: bold;
padding: 0.7em 0.3em 0.2em 0.3em;
}
div.tabContent {
font-family: 'Courier New', Courier, monospace;
font-weight:bold;
font-size: 135%;
font-size: 1vw;
border: 1px solid #696969;
margin: 0 40px 0 40px;
padding: 0.5em;
background-color: #ffe5b3; }
div.tabContent.hide {
display: none;
}
h1 {
font-family: 'Courier New', Courier, monospace;
color:red;
text-align: center;
font-size: 700%;
font-size: 7vw;
font-weight: bold;
}
h2 {
font-family:'Courier New', Courier, monospace;
color:red;
text-align: center;
font-size: 150%;
font-size: 1.5vw;
}
a {
font-family: 'Courier New', Courier, monospace
}
hr {
border-color: #696969;
}

08-Feb-16 23:51
Give us a clue and we will try to help.
09-Feb-16 17:02
What exactly are you looking for by way of clue?
10-Feb-16 09:49
As I said in the previous post ... ... We need to actually see the problem.

Just the CSS rules are of no use to recreate your problem.

EVERYTHING is required, the CSS, The HTML it is applied to and any images used as structural or decorative elements.

As I keep saying to many people who post THEIR problems with Elated tutorials, we need to see YOUR code preferably as a URL so we can view and test 'in situ'
23-Apr-16 07:23
Matt, thanks for the tabbed page tutorial.

I would like to go a little further. Suppose I have a form even on the same page, and when I submit, I would like to return to the same tab. How could that be archived?
25-Apr-16 12:55
See my reply following mashdot's question dated 08-Sep-09 17:35
15-Sep-16 11:05
for camdaw:

Your fixes to the font size helped me a LOT! I am not a coder, just google and play around till it works.

So I am only having one issue now that I'm hoping someone can hjelp me with, and remember, I really have no clue what I'm doing so you may need to give em more details than you think you need to.

So, my text is shrinking and expanding beautifully based on the page size. LOVE IT! BUT, I have images embedded as well that ARE NOT changing size.

How do I fix them? This is how they are currently in my code, so the top part is the label for the image it is shrinking and expanding based on page size, but the image (with link to a document) that I had centered below it using the &nbsp; is not changing:

&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp3rd QTR FY16 DeCA
<br />

&nbsp;&nbsp;&nbsp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp<a href="#" onClick="MyWindow=window.open('https://www.milsuite.mil/book/docs/DOC-306188'); return false;"><img src="https://www.milsuite.mil/book/resources/statics/1737745/DeCA3rdQtrFY16DashboardThumbnail.jpg?a=1472744998785"></a>


THANKS!

[Edited by tmkramer on 15-Sep-16 11:30]
15-Sep-16 18:55
first of all ... Do NOT 'centre' things using non-breaking spaces, as it is just 'guesswork' use the appropriate properties.

And for images:

http://www.w3schools.com/css/css_rwd_images.asp
21-Sep-16 14:53
Is there an alternative to divs in the tabbed content?

I'd like to add something like this:
<div id="follow" style="float: right; width: 48%; margin-top: 40px; padding: 0 0 4px 11px; border-left: 1px solid #ccc;">
to divide sections of the page and then float left and right.

When you add this to the content it creates a divide and moves everything below to the next tab. I'm attempting this on the last tab of my page, but it still breaks away from the content.
26-Sep-16 06:00
"it creates a divide" Yep that's why they are called 'div', shorthand for 'division' (or 'divider')

You can use whatever element you prefer or need.

But first, ... Learn the difference between block level and inline level elements, how to use the 'display' property and floating/clearing elements.

https://www.w3.org/TR/CSS2/visuren.html

Plus how to use positioning to overlay/overlap elements, in the same X-Y space.

[Edited by chrishirst on 26-Sep-16 06:01]
18-Oct-16 08:25
Somebody has an example of multiple section with tabs on the same page? I just cannot seem to get it!

ie:
some text
tab1 tab2 tab3
other text
tab4 tab5
yet other text

View all 301 responses »

Post a response

Want to add a comment, or ask a question about this article? Post a response.

To post responses you need to be a member. Not a member yet? Signing up is free, easy and only takes a minute. Sign up now.

Top of Page