by

CSS

We’re doing a project these days where we use an accordion-menu to show some content.
I want to share with you how I did this using jQuery and CSS. This is pretty easy and I want to encourage you not to use any plugin or so but to write the code yourself and learn a bit more about how to use CSS and jQuery and save some microseconds on your loading type.

The HTML

This is kinda straightforward I think. We don’t need a wrapper for the accordion-menu. Check it:

<section id="experts" class="accordion-item">
  <h1><a href="#experts">Experts</a></h1>
  <div class="content"></div>
</section>

This is how every item for your accordion should look like.

The CSS-Part

Some basic CSS-rules for the header and the content of each item.

.accordion-item h1 a { display: block; font-size: 1.5em; text-align: center; }
.accordion-item .content { display: none; }

You may want to do at least a bit more on the styles but that’s up to everybody on its own.

We want to keep this accordion accessible for people who don’t use JavaScript, what is kinda unusual these days I think… but you never know!
That’s why we added an id to each accordion-item and link to this section in the headline through #experts for instance. We can now show the content of the requested id with CSS:

:target .content { display: block; }

So we’re all set up with the accordion. We can now add some effects with JavaScript.

Using jQuery

First, we will add a line that will show the content of the first element on load:

$('.accordion-item').eq(0).addClass('current').find('.content').show();

And than the we will listen to clicks on the headlines and do some actions afterwards. Read the comments in this snipped.

// Listen to click on headline-link
$('.accordion-item h1 a').click(function(e) {
  // prevent auto scrolling to id
  e.preventDefault();
 
  // Register the variables for better performance
  var $parent = $(this).closest('.accordion-item'),
      $content = $parent.find('.content');
 
  // If the clicked section is not the active one
  if (!$parent.hasClass('current')) {
 
    // SlideUp "old" and remove class
    $('.accordion-item.current .content').slideUp()
      .parent().removeClass('current');
 
    // Add class and slide down content
    $parent.addClass('current');
    $content.slideDown();
 
  // If the click was triggered on the currently active section
  // remove the class and slide up content
  } else {
    $parent.removeClass('current');
    $content.slideUp();
  }
});

And this is it I guess. Working pretty much in every available browser. The CSS :target pseudo-class is not available in every browser though, as it is a CSS3-pseudo-class. And now guess which browser this might be… Right Internet Explorer. It is supported with version 9 but not before.
You will find more information about :target in the spec. Check out the Can I Use table on CSS3-Selectors.

Download the files

I’ve made a demo of this on jsFiddle. Play around a little bit or download the files, if you want to.
Demo     Download