Module CSS Tabs

With basis in the Navigation CSS Tabs this page will propose a method of creating Module Tabs with the help of a little javascript.

Module tabs are used to browse through a stack of panes without reloading the page. For this purpose, we need to use javascript to access the DOM in order to set events for the clicking on the tabs.

The final results will look like this:

Tab 1 content

With starting point in the Navigation CSS Tabs, we have the following code ready at hand:


<style><!--
#header {
  width: 100%;
  float: left;
  border-bottom: 1px solid #aaa;
}

ul.tabs {
  margin: 0;
  padding: 0;
  list-style: none;
}

ul.tabs li {
  margin: 0;
  padding: 0;
  float: left;
}

ul.tabs a {
  text-decoration: none;
  display: block;
  margin: 0 2px 0 2px;
  padding: 3px 10px;
  border: 1px solid #aaa;
  border-width: 1px 1px 0 1px;
  background: #ddd;
  color: #888;
}

ul.tabs a.current {
  background: white;
  color: black;
  margin-bottom: -1px;
  padding-bottom: 4px;
}

ul.tabs a:hover {
  background: white;
}
--></style>

<div id="header">
  <ul class="tabs">
    <li><a href="#">Tab 1</a></li>
    <li><a href="#" class="current">Tab 2</a></li>
    <li><a href="#">Tab 3</a></li>
    <li><a href="#">Tab 4</a></li>
  </ul>
</div>

Which translates into:



What we want to add to this are a content box that holds the content for the tab that is shown and functionality that can toggle the content of the content box.

As we do no longer want the tabs to go across the full page width, but want the module tab box to be defined into a fixed width, we will add a <div> box around the existing code.

We will also create a <div> box for each tab containing the content belonging to that tab. To make styling and the javascript easier, we will also put a <div> box around each of these content boxes. The new HTML will look like this:


<div id="tabs">
  <div id="header">
    <ul class="tabs">
      <li><a href="#" class="current">Tab 1</a></li>
      <li><a href="#">Tab 2</a></li>
      <li><a href="#">Tab 3</a></li>
      <li><a href="#">Tab 4</a></li>
    </ul>
  </div>
  <div class="content">
    <div class="content_tab" id="tab_1">
      Tab 1 content
    </div>
    <div class="content_tab" id="tab_2" style="display: none;">
      Tab 2 content with long text:<br />
      <p>Vivamus ornare, dui eu ultrices ullamcorper, arcu felis mattis magna, a aliquam augue velit iaculis velit. 
         Duis est erat, ultrices nec, scelerisque at, rhoncus vel, nibh. Pellentesque sodales tellus vitae lacus. 
         Vivamus suscipit odio non libero. Sed in sem at mi dictum dignissim. Pellentesque lacinia auctor magna. 
         Morbi felis sem, lacinia iaculis, aliquam mattis, dignissim eu, neque. Aliquam quis sem. Aenean urna mauris, 
         nonummy tincidunt, sodales non, dignissim in, tortor. Integer felis.</p>
    </div>
    <div class="content_tab" id="tab_3" style="display: none;">
      Tab 3 content
    </div>
    <div class="content_tab" id="tab_4" style="display: none;">
      Tab 4 content
    </div>
  </div>
</div>

We will by defining the width of the top layer <div id="tabs"> by adding a css class for it. After that, we will add a CSS class for the the <div class="content"> that surrounds the each of the tab content <div> boxes:


#tabs {
  width: 400px;
}

#tabs .content {
  clear: both;
}

clear: both; makes sure that we break the line for any floats that might be in effect. The tabs have that both in the #header and the ul.tabs li CSS classes. Basically, it’s acts like a <br /> HTML tag – but for both left and right sides.

Next, we need to define the content <div> box itself. We will add a matching style to it right away, with border and padding. We don’t want to have a top border in the content boxes, as the <div id="header"> element has taken care of this already.


#tabs .content_tab {
  padding: 5px;
  border: 1px solid #aaa;
  border-width: 0px 1px 1px 1px;
}

We now have this:


Tab 1 content

But something is missing. We still need to be able to switch between the different panes dynamically without reloading the page. Let’s introduce some javascript:


  function changeToTab(link_element, tab_name) {
    changeCurrentTabLink(link_element);
    changeCurrentTabContent(tab_name);
  }

  function changeCurrentTabContent(tab_name) {
    var tab_elements = document.getElementById('tabs').getElementsByTagName('div')[1].getElementsByTagName('div');
    for (var i = 0; i < tab_elements.length; i++) {
      if (tab_elements[i].className == 'content_tab') {
        tab_elements[i].style.display = 'none';
      }
    }
    document.getElementById(tab_name).style.display = 'block';
  }

  function changeCurrentTabLink(link_element) {
    var tab_elements = document.getElementById('tabs').getElementsByTagName('ul')[0].getElementsByTagName('li');
    for (var i = 0; i < tab_elements.length; i++) {
      tab_elements[i].getElementsByTagName('a')[0].className = '';
    }
    link_element.className = 'current';
  }

Now – this is not the prettiest javascript in the world, but it gets the job done. It was written very quickly specifically for this tutorial. We will use the function changeToTab() to do the magic.

To add this magic into play, we will simply add onclick events to each of the <a> tags that represent a tab in the top horizontal tab bar.


    <ul class="tabs">
      <li><a href="#" class="current" onclick="changeToTab(this, 'tab_1'); return false;">Tab 1</a></li>
      <li><a href="#" onclick="changeToTab(this, 'tab_2'); return false;">Tab 2</a></li>
      <li><a href="#" onclick="changeToTab(this, 'tab_3'); return false;">Tab 3</a></li>
      <li><a href="#" onclick="changeToTab(this, 'tab_4'); return false;">Tab 4</a></li>
    </ul>

The first parameter of the function is the <a> link element itself. The function will handle it and manage to set the right class names. The second parameter is the id attribute of the content box we want to switch to.

As it is now, there is a variable height of the content box. This is not good, if the module tab box is to be a part of a page with a fixed layout as changing heights of the content box can possibly ruin an existing design. Therefore, we will add a final touch to the #tabs .content_tab CSS class: a fixed height of 150px and overflow: auto.

overflow: auto puts scrollbars on the content box if the contents of the box fills up more than the fixed height of 150px.

And now we’re done. You can see the result at the top of the page. The final code is:

<style><!--
#tabs {
  width: 400px;
}

#header {
  width: 100%;
  float: left;
  border-bottom: 1px solid #aaa;
}

ul.tabs {
  margin: 0;
  padding: 0;
  list-style: none;
}

ul.tabs li {
  margin: 0;
  padding: 0;
  float: left;
}

ul.tabs a {
  text-decoration: none;
  display: block;
  margin: 0 2px 0 2px;
  padding: 3px 10px;
  border: 1px solid #aaa;
  border-width: 1px 1px 0 1px;
  background: #ddd;
  color: #888;
  font-size: 0.8em;
}

ul.tabs a.current {
  background: white;
  color: black;
  margin-bottom: -1px;
  padding-bottom: 4px;
}

ul.tabs a:hover {
  background: white;
}

#tabs .content {
  clear: both;
}

#tabs .content_tab {
  padding: 5px;
  border: 1px solid #aaa;
  border-width: 0px 1px 1px 1px;
  height: 150px;
  overflow: auto;
}
--></style>

<script><!--
  function changeToTab(link_element, tab_name) {
    changeCurrentTabLink(link_element);
    changeCurrentTabContent(tab_name);
  }

  function changeCurrentTabContent(tab_name) {
    var tab_elements = document.getElementById('tabs').getElementsByTagName('div')[1].getElementsByTagName('div');
    for (var i = 0; i < tab_elements.length; i++) {
      if (tab_elements[i].className == 'content_tab') {
        tab_elements[i].style.display = 'none';
      }
    }
    document.getElementById(tab_name).style.display = 'block';
  }

  function changeCurrentTabLink(link_element) {
    var tab_elements = document.getElementById('tabs').getElementsByTagName('ul')[0].getElementsByTagName('li');
    for (var i = 0; i < tab_elements.length; i++) {
      tab_elements[i].getElementsByTagName('a')[0].className = '';
    }
    link_element.className = 'current';
  }
--></script>

<div id="tabs">
  <div id="header">
    <ul class="tabs">
      <li><a href="#" class="current" onclick="changeToTab(this, 'tab_1'); return false;">Tab 1</a></li>
      <li><a href="#" onclick="changeToTab(this, 'tab_2'); return false;">Tab 2</a></li>
      <li><a href="#" onclick="changeToTab(this, 'tab_3'); return false;">Tab 3</a></li>
      <li><a href="#" onclick="changeToTab(this, 'tab_4'); return false;">Tab 4</a></li>
    </ul>
  </div>
  <div class="content">
    <div class="content_tab" id="tab_1">
      Tab 1 content
    </div>
    <div class="content_tab" id="tab_2" style="display: none;">
      Tab 2 content with long text:<br />
      <p>Vivamus ornare, dui eu ultrices ullamcorper, arcu felis mattis magna, a aliquam augue velit iaculis velit. 
         Duis est erat, ultrices nec, scelerisque at, rhoncus vel, nibh. Pellentesque sodales tellus vitae lacus. 
         Vivamus suscipit odio non libero. Sed in sem at mi dictum dignissim. Pellentesque lacinia auctor magna. 
         Morbi felis sem, lacinia iaculis, aliquam mattis, dignissim eu, neque. Aliquam quis sem. Aenean urna mauris, 
         nonummy tincidunt, sodales non, dignissim in, tortor. Integer felis.</p>
    </div>
    <div class="content_tab" id="tab_3" style="display: none;">
      Tab 3 content
    </div>
    <div class="content_tab" id="tab_4" style="display: none;">
      Tab 4 content
    </div>
  </div>
</div>

That’s it! Now go build yourself a cool page with module tabs!

This document was last updated at September 09, 2007

1 comment

Post a comment

Required
Required
Will not be published
simple_captcha.jpg
Required
Type the code from the image