Turning a Dictionary List into a FAQ with jQuery

1. October 2008 14:59

Today I had to create a FAQ page.  In order to make this work nicely I started with a simple Dictionary List markup, and some jQuery sugar to make an expand/collapse list.  Although I love prototype.js, jQuery's nesting and inline DOM object creation really comes in handy.

Here is the html markup for the dictionary list (DL)

<dl class="faq">
    <dt>Item 1</dt>
        Description for Item 1 goes in here...

    <dt>Item 2</dt>
        Description for Item 2 goes in here...

The following style will presume that each DT (Dictionary Term) will have an EM tag for the arrow marker, and a STRONG tag for the actual text. The EM tag is forced to a unicode font, so that it will display properly and consistantly in Windows, you could also use images in place of the triangle characters in order to match your UI better.

.faq dt {
.faq dt em {
    /*  Force unicode font for windows machines (XP or higher)
        Linux/Mac should work with Sans-Serif (default). */
    font-family:'Arial Unicode MS', Sans-Serif;
.faq dt.over { color: #0000cc; }
.faq dd {
    margin: 0 0 0.3em 1em;
    border-width:0 0 0 2px;
    border-style: solid;
    border-color: #888888;
    padding: 0 0 0 0.5em;

Now for the javascript, We need to define the Arrow unicode characters to their html counterparts for easier use in the rest of the script.

var Arrow = {
    up: "&#x25B2;",
    down: "&#x25BC;",
    right: "&#x25B6;",
    left: "&#x25C0;"

the enableFAQs function below is the bulk of the logic, I'll break it down inline...

function enableFAQs() {

First, we want to hide all the dictionary definitions (answers).

    $j(".faq dd").css("display", "none");

Next we create a shortcut matching all the dictionary terms within the FAQs. and for each term, we will replace the plain text with an EM tag with the arrow character, and a STRONG tag with the original text.

    var dts = $j(".faq dt");
    dts.each(function(i) {
        var dt = $j(this);
        var txt = dt.html();
            .css("margin-top", (i > 0) ? "0.5em": "0")
            .append($j("<em />").html(Arrow.right))
            .append(" ")
            .append($j("<strong />").html(txt));

Then we assign some mouseover/out logic.

    dts.mouseover(function(event) {
    dts.mouseout(function(event) {

Next comes the fun part, the click event handler... First we need to get a handle on the dictionary term (DT) and the dictionary definition (DD) so we can set them appropriately. After this, I create a local variable as to if the DD is currently visible. After this, I have some commented out methods in case you want to collapse other members before changing the visibility. After that I set the visibility of the DD tag, as well as changing the marker to the appropriate arrow.

    dts.click(function(event) {
        var dt = $j(this);
        var dd = dt.next("dd");
        var visible = !(dd.css("display") == "none")

        //uncomment to auto-close other FAQ elements
        // $j(".faq dt em").html(Arrow.right);
        // $j(".faq dd").css("display", "none");
        if (!visible) {
            dd.css("display", "block");
        } else {
            dd.css("display", "none");

After this, we simply use the DOM ready method from jquery to initialize the FAQs.

$j(function() {

Hopefully this will be helpful to everyone out there. It took me a little while to get this all working as I want it, and I am not the most familiar with all of jQuery's methodology, which is what took me a while.

faq-test.html (2.62 kb)


Comments are closed


Michael J. Ryan aka Tracker1

My name is Michael J. Ryan and I've been developing web based applications since the mid 90's.

I am an advanced Web UX developer with a near expert knowledge of JavaScript.