Making a Fresh Content Accordion

Making a Fresh Content Accordion

When developing a website, it is a great challenge to be able to organize the content in such a way, that it is both intriguing and eye-catching. Not to mention how important it is to prevent information overloading by exposing your visitors to too much data in a single view.

This is why there are certain techniques that help designers group content and show it only if the user is interested in what you have to offer and interacts with the page.

Today we are making a simple, yet eye-catching accordion with the help of CSS, jQuery and the easing plug-in for some fancy effects.

You can go ahead and download the demo files before we continue with step one.

Step 1 – XHTML

As you can see from the demo, the accordion is divided into four sections, each defined by a LI element with a class name of menu. They are positioned inside the main unordered list (ul.container) and share a common XHTML structure:

demo.html

<li class="menu"> <!-- This LI is positioned inside the main UL -->

<ul> <!-- This UL holds the section title and content  -->

<!-- The click-able section title with a unique background: -->
<li class="button"><a href="#" class="green">Kiwis <span></span></a></li>

<!-- The dropdown list, hidden by default and shown on title click: -->
<li class="dropdown">

<ul> <!-- This list holds the options that are slid down by jQuery -->

<!-- Each option is in its own LI -->
<li><a href="http://en.wikipedia.org/wiki/Kiwifruit">Read on Wikipedia</a></li>
<li><a href="http://www.flickr.com/search/?w=all&amp;q=kiwi&amp;m=text">Flickr Stream</a></li>

</ul> <!-- Closing the elements -->

</li>
</ul>

</li>

Each menu LI contains another UL, which forms a title area (li.button), and a content area (li.dropdown).

We then have an anchor element positioned inside  li.button (button being the assigned class name) . This hyperlink is later bound to a jQuery event handler, which slides open the section’s drop down list once the link is clicked.

It is also worth noting that the dropdown list elements are hidden by default with the display:none CSS property as you will see in a moment.

The accordion explained

The accordion explained

Step 2 – CSS

If styled properly, even the simplest idea can make a big difference in the overall feeling your site gives to the visitors.

It is important to take extra care so that the CSS code you produce is valid and that it works well across different browsers. I’ve included all the styles used in the demo below:

demo.css – part 1

body{
	/* Setting default text color, background and a font stack */
	color:#cccccc;
	font-size:13px;
	background: #302b23;
	font-family:Arial, Helvetica, sans-serif;
}

ul{
	margin:0;
	padding:0;
}

ul.container{
	/* The main UL */
	width:240px;
	margin:0 auto;
	padding:50px;
}

li{
	list-style:none;
	text-align:left;
}

li.menu{
	/* The main list elements */
	padding:5px 0;
	width:100%;
}

li.button a{
	/* The section titles */
	display:block;
	font-family:BPreplay,Arial,Helvetica,sans-serif;
	font-size:21px;
	height:34px;
	overflow:hidden;
	padding:10px 20px 0;
	position:relative;
	width:200px;
}

Here we style the main UL – ul.container, which holds the rest of the elements. Lastly, we define the looks of the hyperlinks that act as section titles (notice that the actual background images are not yet assigned).

demo.css – part 2

li.button a:hover{
	/* Removing the inherited underline from the titles */
	text-decoration:none;
}

li.button a span{
	/* This span acts as the right part of the section's background */
	height:44px;
	position:absolute;
	right:0;
	top:0;
	width:4px;
	display:block;
}

/* Setting up different styles for each section color */

li.button a.blue{background:url(img/blue.png) repeat-x top left; color:#074384;}
li.button a.blue span{ background:url(img/blue.png) repeat-x top right;}

li.button a.green{background:url(img/green.png) repeat-x top left; color:#436800;}
li.button a.green span{ background:url(img/green.png) repeat-x top right;}

li.button a.orange{background:url(img/orange.png) repeat-x top left; color:#882e02;}
li.button a.orange span{ background:url(img/orange.png) repeat-x top right;}

li.button a.red{background:url(img/red.png) repeat-x top left; color:#641603;}
li.button a.red span{ background:url(img/red.png) repeat-x top right;}

/* The hover effects */

li.button a:hover{ background-position:bottom left;}
li.button a:hover span{ background-position:bottom right;}

.dropdown{
	/* The expandable lists */
	display:none;
	padding-top:5px;
	width:100%;
}

.dropdown li{
	/* Each element in the expandable list */
	background-color:#373128;
	border:1px solid #40392C;
	color:#CCCCCC;
	margin:5px 0;
	padding:4px 18px;
}

The most interesting part here is how we specify the individual background property for every section color. We also provide a background for the span element, which holds the right part of the background image, as explained in the illustration below.

The buttons

The buttons

Step 3 – jQuery

After we’ve laid the layout of the accordion, it is time to make it tick. First we need to include a few scripts in the page (this code is put inside the head section of the document):

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script>
<script type="text/javascript" src="jquery.easing.1.3.js"></script>
<script type="text/javascript" src="script.js"></script>

We first include the jQuery library from Google’s CDN, which will help us write compact and compatible code. Later we include the easing plugin and lastly our own script file, which I’ve covered in detail below.

As you may have noticed from the demo, the slide down effect is not your regular linear movement, but more bounce-like and lively. This is achieved with the help of the easing plug-in for jQuery. It provides a number of interesting effects which can put those lovely details in your web design.

Now lets continue with our own scripts file.

script.js

$(document).ready(function(){
	/* This code is executed after the DOM has been completely loaded */

	/* Changing thedefault easing effect - will affect the slideUp/slideDown methods: */
	$.easing.def = "easeOutBounce";

	/* Binding a click event handler to the links: */
	$('li.button a').click(function(e){

		/* Finding the drop down list that corresponds to the current section: */
		var dropDown = $(this).parent().next();

		/* Closing all other drop down sections, except the current one */
		$('.dropdown').not(dropDown).slideUp('slow');
		dropDown.slideToggle('slow');

		/* Preventing the default event (which would be to navigate the browser to the link's address) */
		e.preventDefault();
	})

});

We first set the easing method that is going to be used by the slideUp/slideDown effects, and then bind a specially crafted function to the click event of the li.button hyperlink. When this link is clicked, we get the corresponding li.dropDown and show it, hiding all the others.

I am using the slideToggle jQuery method, which checks to see if the element is already visible on the page, and decides whether to show or hide it. This way, when you click on an open section of the accordion, it is contracted instead of just staying opened.

After this, we use e.preventDefault() to prevent the browser from navigating away from the page (after all we’ve just clicked a link and this is the normal behavior).

With this our fruity CSS & jQuery accordion is complete!

A CSS & jQuery accordion

A CSS & jQuery accordion

Conclusion

This time we created a fresh accordion script that is both easily modifiable end embeddable.

Can you think of any awesome uses of this script?

How would you like to change it?

Join our newsletter and get our PSDs!20,263 people learn about HTML5, JS and more. Join them!

by Martin Angelov

Martin is a web developer with an eye for design from Bulgaria. He founded Tutorialzine in 2009 and it still is his favorite side project.

55 Comments

  1. Hoditta says:

    It was amazing.... thanks ;)

  2. Chris says:

    Great stuff - would it be possible to show how perhaps it could be extended to another sublevel deep? (ie an accordian within an accordian) I got need for just that and can't find a decent example anywhere.

    Any help would be great.
    Cheers

  3. Nice one..

    Is it possible to ease the content inside to right or left rather than to the bottom.. It would be helpful..

    Regards
    -Arjun S Kumar.
    :)

  4. David Moreen says:

    Oh god that is so beautiful.

  5. Joel says:

    Great job with this one. I'm excited to try it.

  6. Andrew says:

    Еxcellent, i love tutorialzine, but the file of css is not included in your demo.

  7. Martin says:

    @ Chris

    Actually it won't be that difficult to do - you'll have to duplicate the whole accordion xhtml structure (from step 1) and paste it inside of every li.dropdown you want to be shown as multilevel.

    The other step is tricky however - you'll have to change the CSS, because li.dropdow has default styles that you do not want to mess up your sub-accordion.

    Other from that, jquery should work fine (it is made with a relative parent and dropdown, depending on the link clicked, so it should find its way).

    @ Arjun

    Yes, it is possible, but it won't be easy. You'll have to change the XHTML structure and use the jquery animate method and make it expand to the right, instead of slideDown.

    @ Andrew

    Sorry about that. I re-uploaded the archive.

  8. Chris says:

    Thanks - can you just expand on this comment a little more...

    "The other step is tricky however – you’ll have to change the CSS, because li.dropdow has default styles that you do not want to mess up your sub-accordion."

  9. Nice. I'd like to see more JQuery tutorials with PHP, showing how to make those menu options dynamic.

    But this is still good.

  10. Another Beauty Martin. Nice work bro.

  11. arnold says:

    Oh my... and you use some sprites also , very cool .
    Now subscribing...

  12. Melvin José says:

    Looks pretty nice.
    I think this would be pretty cool with images.

  13. Blogger Den says:

    This is awesome! I can definitely use something like this on my new social networking site, and the tut is really easy to follow

  14. @Martin

    Thanks for the info. I'll try it out and ask you if I come across any difficulty..

  15. thanks a alot.....simple & clearly explained :)

  16. One major problem with this, although the xhtml and css are very good, is that you're allowing animations to build up. Try clicking an accordion title many times and you'll see. The solutions is to simply add a .stop() like this:

    dropDown.stop().slideToggle('slow');

  17. Martin says:

    @ Add My Website

    Thanks for the notion. Although the stop() method works great for jQuery animation(), it is a bit more tricky when it comes to slideUp and the other show/hide methods.

    To make it work with those, you'll need to pass additional parameters to the stop() method, so that line 15 of script.js becomes:

    dropDown.stop(false,true).slideToggle('slow');

    This will successfully prevent animation build up.

  18. WebDev says:

    Re: How would you like to change it?

    Uhh yeah, what's so great about this menu or jQuery in general? To me this is like going backwards in Web Development.

    1. How can this menu be updated from a CENTRAL POINT without having to re-paste the same div navigational "li" and "ul" elements on each successive html page? And I don't want to hear any re-posts about server-side includes either, as most hosting companies worth their salt don't allow SSI for security reasons. Are we then forced to turn every single page into a dynamic (PHP, JSP, .NET, etc.) page just to be able to use and include statement to update a simple jQuery menu from a central file? Talk about a pain.

    2. When JavaScript is OFF or gets turned OFF then jQuery goes buh bye. How is it good that people want to use MORE JavaScript? For years developers and users have been complaining about too much JavaScript being used, lack on scripting consistency between browser engines, security concerns... and here we are PILING it all back on (in jQuery heaps) all over again. Yeah, let's go backward in web development!

    3. jQuery is just an attempt to mimic Flash, so why not just use Flash? Flash doesn't die when the JavaScript lights go OFF. And Flash can be updated from many central points like text files, databases, or XML files.

    From an updating standpoint and from a programming standpoint... I'm just not seeing much to the point of MORE JavaScript (jQuery) in a web world were there is already too much janked JavaScript and where people get upset and kill JavaScript because their browser engine messes it up, or where a security program flips the JavaScript OFF switch, all killing jQuery instantly. jQuery is just more JavaScript... so why are we going backwards in web development with jQuery?

    1. zedgee says:

      @webdev

      Firstly - I think this is the wrong place to leave a comment like this. This is a nice piece of javascript for those who want to use it - not a preaching article on why you should use javascript.

      People may have wanted to use less javascript 10 years ago - but these days it is more lightweight and more widely useable than flash, silverlight or other plugin requiring code. Clients don't really give a shit whether the iphone SHOULD have flash - fact is they want animations, they want application style functions and they want interaction on mobile devices (on all mobile devices, not just iphones).

      Don't get me wrong - I think flash is great for what it does - animations, web games, fully actionscripted interaction. Its just not necessary for these small interactions which just work better using jquery.

      Im afraid to say you just sound old-fashioned - Jquery works pretty well for these simple elements - and noscript is on the whole, a much easier degradation to implement than some kind of noflash alternative (of course we all know the easiest way to add noflash alternative content is using javascript)

  19. Anassin says:

    way better than the jquery plugins

  20. Eduard says:

    I would like to know how can I use this menu and have the first button activated upon page initialization. In other words, I would like to have the first item, say "green" class be already in a dropdown mode whereas the others in a slideUp mode. How do you think I should proceed with this idea?

  21. Martin says:

    @ WebDev

    Thank you for your comment. However I do think that introducing client side scripting benefits the end user and brings web development forward, not backward.

    Some of the shortcomings of JS (such as inconsistencies between browsers) are easily overcome with the use of libraries like jQuery, which take development one step further.

    @ Eduard

    You can simulate a click on the first element on page load. Something like this on line 20 of script.js:

    $('li.button a').eq(0).click();

  22. Eduard says:

    You are awesome. Thank you very very much. I did not even expect to hear back from you. Oh thank you kindly!

  23. Devin says:

    Hey Martin,

    Say I have my own menu system which contains one link to have a drop down like this:

    Design
    link link link link link

    Is this possible? So instead of the drop down and each link under the next, they would show up to the right of each other.

    Also could each link drop down at a slightly separate time, like a wave effect?

  24. Very clean article, I like the design, and I like the step by step methods - thank you very much!

    The picky Art Director in me only would like to see XHTML die in tutorial references; it's the way of the DoDo for me, and I teach my younger designers (younger in experience not age) to move into semantic HTML (we're starting to use HTML5 already, and all of our company sites will move that way in the next few months). But that's nitpicking, I know, and there's some debate on that of course;)

  25. Swati says:

    Hi Martin,

    Love your style of tutorial! I am fairly new to jquery and web design on the whole.

    Could you please explain the need of using in this tutorial?

    Many thanks
    Swati

  26. mom says:

    Instead of a menu, can html be put into its place? Like the accordion on www.blogussion.com?

  27. Blaine says:

    Is there a benefit to using " e.preventDefault()" over return false?

  28. Patrick says:

    Hello, Very helpful and informative article! I adapted the accordion used here to hold dynamic wordpress content rather than just menu items, but I've run into a snag and was wondering if you had any advice. It seems unless I specify a fixed height for the DIV I'm applying the effect to, the easing effect lasts about half the height of the DIV then snaps to the bottom. It changes from DIV to DIV, longer ones ease further than shorter ones, but not all the way to the end. Since the content will be dynamic I'd rather not set fixed heights. Any Insight would be greatly appreciated. Thanks.

  29. Patrick says:

    Hi again. You can disregard the above post, I figured it out. :) Turns out I overlooked setting a fixed width for the ".dropdown li" element. It seems it was calculating the width of the whole page to get the height of the div, and then snapping the element down to the width of it's container causing the glitch i described above. Thanks again for the article, helped bunches.

  30. Savio says:

    Is it possible to set one of the sections to be already opened when the page loads? How can I do that? Thanks for the help!

  31. Benjamin A says:

    I needed to know can one set a third level on the menu item

  32. Jackson says:

    Please help me to set one of the sections to be opened when the page loads?
    can any one help me Thanks!!

  33. jackson says:

    hi i found that solution which you have posted for Eduard, thanks.
    one more thing i need to know to fix its hover state should be active when its opened...

  34. iMayne says:

    Can seem to import this in my .php. Too many conflicting css. Damn!!!!

  35. Amjad says:

    Good job.

  36. Nico says:

    What a fantastic set of tabs!!

    Also a very helpful post!!

    I to have one question, how do you display the current state of the selected tab?

    THANK YOU in advance for the help

  37. Devesh Sharma says:

    Cool accordion! Good job!

  38. Rollout says:

    Nice Nav tool.

    I am using this for my navigation. Presently, it is configured similar to your sample...when a user clicks on a main heading, the list opens to reveal items below it. No new page loads. The user can now scroll down the list, click on an item, and be taken to a page.

    I would like this behavior instead: when a user clicks on a main heading, a corresponding page loads AND the list opens to reveal items related to that heading.

    The code in the script.js file makes opening a page when a main heading is clicked possible, but it disables the list opening feature. I would like both to happen.

    Any suggestions?

  39. Ryan says:

    Hey Martin,

    Awesome work here, I really appreciate it.

    I had a little trouble with the js but after a little googling found replacing line 46 in jquery.easing.1.3.js with this helped:

    return $.easing[$.easing.def](x, t, b, c, d);

    Thanks again!

  40. Mehmet says:

    Selected element.

    Something like this on line 20 of script.js:

    //first element on page load
    $('li.button a').eq(0).click().addClass('active');

    //active element
    $('li.button a').click(function() {
    $('li.button a').removeClass('active');
    $(this).addClass('active');
    });

    And in css:

    li.button a.blue.active { color:#fff; }
    li.button a.green.active { color:#fff; }
    li.button a.orange.active { color:#fff; }
    li.button a.red.active { color:#fff; }

  41. Dorothy says:

    Hello, thank tou for the tutorial, its great, I used it for my training, It works exellent, though, there is a small problem. I have another new div below with id="content", and when I open the accordeon menu, it pushes down the div id="content", could please tell me the reason, why it happens.
    Thank you in advance.

  42. Igor Jovanovic says:

    Hello Martin,
    I neеd your help!
    I want to add a new submenu to get third level (e.g. Kiwis > Open Grapes Section > and my new submenu).
    Is it hard to do that? My knowledge of this is equal to zero.
    Thanks in advance!

  43. Kimberly says:

    Hi Martin, this tutorial is great! One question - if you would like to have one of the sections, such as Grapes, already expanded when a user clicks on the page, how would the code be adjusted?

    Thanks!

  44. Javier says:

    Hello Martin very good script, would need help getting the horizontal submenu vex down, you could hecharme quisas hand or know any script to take as an example, thanks in advance, greetings

  45. Chris says:

    I've run into a bit of an issue. I am using your accordion to show/hide a content div with a button click. Everything works great until I try to use the same html etc. in WordPress. Is there anything I can try to get it working on a page in wordpress. Thanks!

  46. Mahesh says:

    Good Article. I have used in my project

  47. Francis says:

    @Martin

    Hi Martin,

    Many thanks for this tutorial.

    Is there any way to keep the expanding effect but without the bounce?

    Thanks!

  48. Codemaster Gabriel says:

    Amazing work !!!

  49. Yasser says:

    i want 3 level accordion for this great example

  50. Tom says:

    Great tutorial, thanks!

    I've been looking for accordion tutorials, but most only explained the basics and had rudimentary design. This one is top-notch!

  51. CARLOS says:

    HI, GREAT TUTORIAL,

    Is it possible to put an accordion inside another accordion? if it is too complicated, i'm willing to hire you.

    thanks for the tutorial!

    Carlos Pinedo

Add Comment

Add a Reply

HTML is escaped automatically. Surround code blocks with <pre></pre> for readability.
Perks:   **bold**   __italics__   [some text](http://example.com) for links