jQuery Accordion with 8 Lines of Code

Ok.  Maybe more than 8 lines of code but very little.  I have been working with another agency (that will rename nameless) on a mobile web site for a client of ours.  The agency provided the HTML/CSS/Images and Script for our technology team to implement.  We hook up all the back end and call it a day.

The section that came into question was an ‘accordion’ style UI for a set of FAQ’s and other content.  When I first loaded up their pages, everything worked fine.  Upon further inspection of their code I noticed a lot of JavaScript libraries that were not needed.  They included jQuery AND Prototype along with some effects and accordion scripts.  (Prototype alone is almost 100kb in file size and the other scripts were 42kb.  That still does not include the 70kb for jQuery)  I thought to myself, this is a mobile site…why have extra scripts if not needed.  To make matters even more funny, we are supporting Mobile Safari (iOS), Mobile Chrome (Android) and the BlackBerry Browser (RIM), it does not work in BlackBerry at all.  Forget enabling or disabling JavaScript it just does not work.  Even the elements are hidden.

So it got me thinking about the old saying, “if you want something done right you have to do it yourself”.  So I did.

I removed all the libraries except for jQuery and made all of the elements visible by default.  Basically if a user does not have JavaScript enabled then they can see everything.

Here is my HTML

Styles and other HTML can be wrapped around it. You can change the paragraph tags to div’s if needed but that is the structure you need more or less.

Now for the JavaScript.

Make sure you embed jQuery (I did from Google)

Then hide all open content containers:

If the element does not have the ‘current’ class then we need to first remove the ‘old’ ‘current’, close the ‘old’ ‘current’ and open and set the new ‘current’.

Done.

Here is the final:

Depending on how you format the code and what you count as a ‘line’ it can be about 8 lines 🙂

Updated GitHub Repository

Demo here – View in Mobile Browser.  Desktop browser will work as well.  Works on iOS, Android, BlackBerry.

Leave a Comment

(19 Comments)

  • Nach

    So simple and so useful. Thanks for posting your solution!

  • Steven

    How do you have one opened by default when the page loads?

    • Josh

      Easy. Add a class to the accordion_content div called “open”.

      In the JS where the first hide() event is called, change it to $(‘.accordion_content’).not(‘.open’).hide();

      This will hide all dive except the one you want to stay open. Still 8 lines 🙂

      • Steven

        Thanks for the quick reply,

        However, it doesn’t seem to work properly. I would like to have it close when another is opened. Additionally, the arrow doesn’t point down when the page loads.

        • Josh

          Sorry. I forgot a class. Add ‘current’ to the accordion_toggle that is supposed to stay open.

          Not sure about the arrows. I would add a style for current that has an open arrow.

  • C. Hoods

    This is awesome, thank you so much for posting! Is there a way to automatically detect if a user does not have javascript enabled? If so, I’d like to maybe direct them to a version of the page without the accordion (maybe just regular links).

    • Josh

      Actually, if the user does not have JS enabled the page will render just fine, with all links open. Right now the JS is closing the content so if no JS then content stays open.

  • Steve

    Thanks for this!

    I currently using html5 and trying to get this.

    Blah Blag Blag

    Now I want to hide the footer and the section element, I tried this.

    $(‘.tab-links, .comments’).hide();

    but it’s not working.

  • Steve

    My comment above hasn’t displayed correctly, attempting to explain this again

    At the moment I have

    [article]
    [p][/p]
    [footer class=comments][/footer]
    [section class=tab-links][section]
    [/article]

    I’m trying to use

    $(function() {
    $(‘.tab-links, .comments’).hide();

    $(‘article p a’).click(function(e){
    if($(this).parent().hasClass(‘current’)) {
    $(this).parent()
    .removeClass(‘current’)
    .next(‘.tab-links, .comments’).slideUp();
    } else {
    $(document).find(‘current’)
    .removeClass(‘current’)
    .next(‘.tab-links, .comments’).slideUp();
    $(this).parent()
    .addClass(‘current’)
    .next(‘.tab-links, .comments’).slideDown();
    }
    e.preventDefault();
    });
    });

    but it’s not working on the section element. or any second element under the first.

    • Josh

      Correct me if I am wrong, you are trying to open and close 2 elements? So if a user clicks on the ‘a’ tag the footer .comments and the section .tab-links both open?

      Why have them in separate containers? Why not just in one?

      Do you have the HTML somewhere I can look at?

  • Steve

    You are correct, but I want them in separate containers for good structural and semantic meaning.

    Is this possible? Can I select two classes so they both open? Or am I limited to just one with this script?

    Thanks.

  • Josh

    create a common class to use just for the 2 elements. like this
    [footer class=”comments hideme”][/footer]
    [section class=”tab-links hideme”][/section]

    and them in JS just reference hideme

    • Steve

      Tried that Josh, it doesn’t unhide the second element (Section class=”tab-links”) when clicked.

  • Steve

    I’ve decided to just wrap the elements in a div tag, easier that way.

    Thanks for your assistance guys, really appreciate it.

    • Josh

      The reason is it has to do with the daisy chaining of the script. The code is looking at the parent next element (which in your case is the comments class) while the tab-links element is being ignored. If you add another daisy chain of .next(‘.tab-links’).slideUp() it should work. I added another example here http://drew5.net/examples/accordion-example/example2.html

  • Steve

    Ah, I see, I’ve only started using jQuery so I’m a bit dopey on the whole concept, thanks for the example, using it right now!

  • Steve

    May I just ask, is it possible to have another accordion within another?

    Thanks!

  • Steve

    At the moment I have:

    $(function() {
    $(‘.hidden, .hidden2’).hide();
    $(‘article p a’).click(function(e){
    if($(this).parent().hasClass(‘current’)) {
    $(this).parent()
    .removeClass(‘current’)
    .next(‘.hidden’).slideUp()
    .next(‘.hidden2’).slideUp();

    } else {
    $(document).find(‘.current’)
    .removeClass(‘current’)
    .next(‘.hidden’).slideUp()
    .next(‘.hidden2’).slideUp();
    $(this).parent()
    .addClass(‘current’)
    .next(‘.hidden’).slideDown();
    $(‘article footer li a’).click(function(e){
    .next(‘.hidden2’).slideDown();
    }
    e.preventDefault();
    });
    });

    But it’s sending an error back to me, this is all a learning curve for me, so bare with me.

  • Grover

    Just FYI, the sample HTML you have there is incomplete. You’re missing the surrounding P or DIV with the class=”accordion_toggle”.

    Thanks for sharing this.

  • Your email address will not be published. Required fields are marked *