FAQ with jQuery

Let's have a look at how you can add some jQuery to make a static FAQ page more appealing to your visitors. To start our example have a look at the demo FAQ. The basic layout of the page is this:

<div class="faq">
<p class="question">Question</p>
<p class="answer">Answer</p>
</div>

The outer div allows for specific CSS rules should you need them, but is not used in this example. Next are pairs of paragraphs, where the first contains the question and the second the answer, repeated as needed. Each paragraph is also marked by a class, so we can use it in CSS to style them.

Adding jQuery

Now we add jQuery to this page. Download the latest minified jQuery file, currently 1.4.2, and put it in the same folder. Before the </body> tag withing the <head>, add:

<script type="text/javascript" src="jquery-1.4.2.min.js"></script>

It is also possible to use a hosted version on a CDN (Content Delivery Network), like Google or Microsoft. If you want to do this, you can add one of the following two lines instead:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js" type="text/javascript">
</script>
<script src="http://ajax.microsoft.com/ajax/jquery/jquery-1.4.2.min.js" type="text/javascript">
</script>

Next, we create a new file (called jq-faq-1.js) to contain our javascript (jQuery) code, put it in the same folder and add the following code after the previous one:

<script type="text/javascript" src="jq-faq-1.js"></script>

In this last file we add the following code:

$(document).ready(function() {
$('.answer').hide();

$('.question').live('click', function() {
$(this).next().slideToggle();
});
});

The result should now look like the second demo FAQ.

What it means

I've been quick to show you how to do it, but what does it actually do ? I'll explain it line by line.

$(document).ready(function() { });

This line tells jQuery to execute everything, within the function, when the page is done loading. If you don't, then some elements may not be accessible yet, and your jQuery code may fail. I will not get into detail here, more is explained in the jQuery documentation.

$('.answer').hide();

This line tells jQuery to start looking for all classes named "answer", and hide them. ".answer" is called a selector. jQuery does all the work for you (traversing the DOM tree) and will return a collection of matching elements. For each of these elements, the hide() function is called. This does the same as you would, when you would put the following in CSS:

.answer { display: none; }

This will leave only the question(s) visible on your page. The reason we do this in jQuery, and not in CSS, is that if someone has javascript disabled, he will still see the original page with all the questions and answers.

$('.question').live('click', function() {
$(this).next().slideToggle();
});

The first part of this line selects all elements tagged with the class name "question". It then executes the live() function, which connects the elements with the "click" event, which is the left mouse click. The second parameter is the function to execute when this happens. $(this) points to the active element (which has been clicked in this case). Function next() selects the element following the current one. In our example, when you click a question, the next element is the answer. On this element (the answer) we execute the slideToggle() function. This will hide the answer if it's shown, or show it when it's hidden. The switch between these states will be animated relatively smooth. Technically speaking we're done.

Display issue in IE 

When I was first testing this, everything appeared to be in order. Opera, Safari, Chrome and FireFox all worked as expected. Internet Explorer looked fine too, but it wasn't really. When you try harder, click more often, you'll notice that the display in IE is jumpy. After some searching I came across similar issues. The rendering in IE is buggy. The problem can be traced back to the use of margins (top or bottom specifically). Since most elements have a default margin, you have to set them to zero and the jumpy display stops.

Now we have no margin, to get the display working, we have a layout issue. The elements are now cluttered together, which is not visually appealing. To fix this, we can restructure our HTML and use some CSS. The new HTML will look like this:

<p class="question">
Question
</p>
<div class="answer-wrapper">
<p class="answer">Answer</p>
</div>

Part of the new CSS is this:

.question {
margin: 0;
padding: 10px;
}

.answer-wrapper {
margin: 0;
padding: 10px;
}

.answer {
margin: 0;
padding: 10px;
}

The javascript file also needs a small change:

$('.answer-wrapper').hide();

As you can test on the final demo page, this also works in IE, as it does in the other browsers. Of course, there are more ways to skin this cat. Just remember that IE gets nervous when showing/hiding elements with a margin. Hopefully this will revert into a non-issue in upcoming versions.

Download files

I've put my example files up for grabs, so you won't have to scrape my website.