Expand/Collapse Hidden DIV or TR Content

This is one of those tricks that once you learn it, you're amazed you ever lived without it. The ability to hide certain content on a page and then display it when the user wants to see it is actually quite easy to pull off. Here, I'll show two methods I use a lot in my work; hidden DIV content and hidden table rows.

First, an example of what we're talking about:

 Click for more...

Doh, you found me!

There are really four components to this effect:

  1. Some element that gives the user a hint that there's more to be seen. In the example above, we use a small image and the text "Click for more...".
  2. The hidden content written to the page but with a class attribute that keeps it from being displayed.
  3. Stylesheet entries for both the hidden and visible states. In our example, we use the class names 'hiddenRow' and 'visibleRow' respectively.
  4. Finally, some JavaScript that gets executed when you click on the image or text next to it. We've put our JavaScript in a funtion called showHide() but you could also do it with inline javascript.

Let's step through each of these components 1 by 1. First up is the expand/collapse graphical element that gives the user a hint that there's more to be seen. We're using two very simple graphics for this:

expand.gifand collapse.gif

Now we need to write the image to the page along with some text that helps to set the viewer's expectation that they'll see more if they click their mouse:

<img id="image1" border="0" src="/images/expand.gif" valign="ABSBOTTOM" onClick="showHide('divHidden','image1');" style="cursor:pointer;">&nbsp;
<span style="font-weight:bold;cursor:pointer;color:blue;" onClick="showHide('divHidden','image1');">Click for more...</span>

Simple, but effective.

You can see from the code above that the image was given an ID and both the image and text next to it (Click for more...) have onClick() events that call our JavaScript function.

But before we get to that, let's write our hidden content:

<div id="divHidden" class="hiddenRow" style="clear:both;border:1px solid #8E8E8E;margin-left:16px;padding:2px;width:389px;">
Doh, you found me!
<br clear="all">
</div>

In our example above, the hidden text is positioned directly beneath the link that displays it (what most people would expect) but obviously you could just as easily put the hidden content someplace else on the page... that's up to you.

See the class="hiddenRow" bit? That's what keeps the div from being displayed when the page is first loaded.

Which leads us to the stylesheet entries you'll need to setup for this all to work.

.hiddenRow {
 display:none;
 visibility:hidden;
}
.visibleRow {
 display:;
 visibility:visible;
}

Place these in your existing stylesheet or within the <head></head> tags of your site wrapped with <style></style> tags.

Lastly, the JavaScript that is executed when the image or text is clicked:

<script language="JavaScript">
<!--
 
function showHide(HID,IMG) {
        if (document.getElementById(IMG).src.indexOf('expand') != -1) {
                document.getElementById(IMG).src='/images/collapse.gif';
                document.getElementById(HID).className='visibleRow';
        } else {
                document.getElementById(IMG).src='/images/expand.gif';
                document.getElementById(HID).className='hiddenRow';
        }
}
 
// -->
</script>

Now of course there are many ways to accomplish this task and the method I'm using here is rather simple. What I like about doing it this way is the state of the expand/collapse graphic is always in sync with the hidden content. For those new to scripting, let's dissect this function and figure out exactly what it's doing...

function showHide(HID,IMG) {
This line defines our function with the name showHide and declares two variables that will be used within the function: HID and IMG. We could have used almost anything for these variable names... HID is just meant to represent the hidden element you want to either show or hide and the IMG is the expand/collapse graphic the user will have clicked on. When choosing names for variables in your JavaScript functions, remember to stay away from any reserved words for that programming language. For a complete list of what to avoid for JavaScript, check this out.

if (document.getElementById(IMG).src.indexOf('expand') != -1) {
Here we start an IF statement and make use of the JavaScript indexOf() method to see if the referenced image has a source value that includes the word "expand". As we've named our expand/collapse indicator graphics expand.gif and collapse.gif, if the graphic currently displayed is the expand image, we know that the hidden content is not displayed yet and the user is asking to see it. So the next bit of code changes the graphic to the collapse image and then updates the hidden element's className value to make it visible.
document.getElementById(IMG).src='/images/collapse.gif';
document.getElementById(HID).className='visibleRow';

If the src doesn't contain the word expand, we know that it must be set to the collapsed image and the hidden content is already displayed. So we switch from making it visible to making it hidden:

document.getElementById(IMG).src='/images/expand.gif';
document.getElementById(HID).className='hiddenRow';

Look back again at the onClick method we attached to the image and text next to it:

onClick="showHide('divHidden','image1');"
Having looked at the showHide() function a little closer, I hope it makes a bit more sense now. We're simply calling the showHide() function and passing in references to the hidden element and collapse/expand graphic (by way of their Document Object Model ID). The function figures out the current state of the hidden content by using the graphic's source value and then either hides or displays things.

Okay, so earlier I mentioned that I also use this same method with HTML tables and hiding/displaying table row (TR) content. To wrap things up, let's do one more example but this time with a table instead of <DIV> elements.

Click for more...
  Doh, you found me!

The HTML used for this example:

<table border="0" cellpadding="0" cellspacing="0" style="width:400px;border-collapse:separate;">
  <tr onClick="showHide('rowHidden','image2');">
    <td style="width:11px;padding:0px;"><img id="image2" src="/images/expand.gif"></td>
    <td style="width:389px;font-weight:bold;cursor:pointer;color:blue;">Click for more...</td>
  </tr>
  <tr id="rowHidden" class="hiddenRow">
    <td style="width:11px;padding:0px;">&nbsp;</td>
    <td style="width:389px;border:1px solid #000000;">Doh, you found me!</td>
  </tr>
</table>
As you can see, the class="hiddenRow" is now applied to the <TR> we'd like to hide. We've given the expand/collapse graphic a new "image2" id and the hidden element's id is now "rowHidden" but we're still using the same JavaScript function we wrote earlier, we just pass in the updated ID values:
onClick="showHide('rowHidden','image2');"
One advantage to using an HTML table to hold things together is that you can assign the onClick method to the entire <TR> that holds the expand/collapse graphic and Click for more... text.

Something to remember when using HTML tables in this manner is to always set the overall width of the table AND individual <TD> cells. If you don't specify widths that add up properly to the overall table's width, you'll experience shifting of content when the hidden <TR> and it's cells are displayed (especially in Firefox and Safari).

That's it... I hope you found this overview helpful!