John Vine

Creating An Accordion List Without Javascript

Est. Reading Time: 4 minutes

Many sites implement accordions for everything from menus and navigation to product features to calendar event details. The fact is that accordion lists are among the most popular implementations of javascript and can be seen in some implementation on almost every web application and most advanced web sites. With the recent explosion of mobile devices accessing the web there has been a lot more value placed on responsive design. One facet of that has been developing sites without relying on javascript which has been the most common way of generating rich media experiences for users. Some things simply can’t be done without javascript, but other things can be accomplished with a bit of innovation. Accordion lists are just one of many things commonly done in javascript that can be done even in browsers either with scripts disabled or not supported at all.

A typical html snippet for a list might look like this:

<ul id="accordion">
    <li>
        <h3>Section 1</h3>
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
    <li>
        <h3>Section 2</h3>
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
    <li>
        <h3>Section 3</h3>
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
    <li>
        <h3>Section 4</h3>
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
</ul>

A script would then operate on the items in order to provide them the desired behavior to expand and contract on click or hover. With a few simple modifications that same behavior can be accomplished without needing to rely on scripts being enabled on your customers browser (changes in red):

<ul id="accordion">
    <li>
        <label for="section-1-checkbox">Section 1</label>
        <input id="section-1-checkbox" type="radio" name="accordion-level-1" />
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
    <li>
        <label for="section-2-checkbox">Section 2</label>
        <input id="section-2-checkbox" type="radio" name="accordion-level-1" />
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
    <li>
        <label for="section-3-checkbox">Section 3</label>
        <input id="section-3-checkbox" type="radio" name="accordion-level-1" />
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
    <li>
        <label for="section-4-checkbox">Section 4</label>
        <input id="section-4-checkbox" type="radio" name="accordion-level-1" />
        <div>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    </li>
</ul>


<style type="text/css">
    #accordion input[name=accordion-level-1]:not(:checked) + div { display: none; }
    #accordion input[name=accordion-level-1]:checked + div { display: block; }
    #accordion input[name=accordion-level-1] { width: 0px; height: 0px; margin: 0px; opacity: 0.0; }
    #accordion label { cursor: pointer; }
</style> 

We’ve changed the h3 tags to labels and added for attributes pointing at the radio inputs that have been added next to the content that we want to toggle between displayed and hidden. The first two rules dictate which content is displayed based on the state of the radio button that precedes each content section. The third rule hides the actual input since it’s unlikely you want random input tags cramping your style (pun intended). The fourth rule simply provides feedback to your users on hover that the element is clickable. If you want to enable the expansion on hover the second rule can be changed to “#accordion li:hover div { display: block !important; }” and take special note of the !important attribute on that style. This is because the nature of styles will dictate that the first rule overwrite the second due to its specificity.

Obviously one of the drawbacks of this method is the lack of animation since animation was only possible with javascript prior to html5. The good news is that once this html/style accordion has been implemented you can also add scripts to you page to implement the accordion using script for those users that do have script enabled and render the styles we added for the scriptless version inert by simply removing the radio inputs from the DOM. Now your accordion can expand and contract both with and without script, though admittedly it will probably look better when scripts are enabled.

2 Comments

  1. Posted February 8, 2013 at 6:57 am | Permalink

    Great tip! I love it.

    If you change the radio button to a checkbox, you get slightly different functionality that some users may prefer. With a checkbox, accordion text toggles open and closed with successive clicks. With the radio button, you can only close the accordion for section 1 by clicking on section 2.

  2. Posted February 8, 2013 at 7:04 am | Permalink

    That’s an excellent point and one I’m glad was brought up. There are strong points for both cases. With radio buttons opening a new “tab” will automatically close other open tabs, but as you pointed out there is no way to then close an opened tab without opening another. With checkboxes each tab can be toggled open and closed independently from other tabs, but would allow the user to expand your entire accordion. It really is a matter of which fits better in your web site. Thank you so much for the great feedback!