Simple Accordion w/ CSS and jQuery
When designed and implemented with usability in mind, the accordion can be incredibly useful when organizing a good chunk of content. Since a lot of people found my toggle tutorial useful, I would like to go over how I approached building an accordion from scratch.
Foundation – HTML
Our markup is pretty simple, an <h2> and <div class="acc_container"> following right after. The <h2> is the heading of our accordion item. We will be using this as our trigger w/ jQuery. The <div class="acc_container"> is what will be sliding up and down to show its content.
<h2 class="acc_trigger"><a href="#">Web Design & Development</a></h2>
<div class="acc_container">
<div class="block">
<!--Content Goes Here-->
</div>
</div>
Styling – CSS
There are two important parts to pay special attention to in the styles.
- Fixed width on the
.acc_container(Cannot be in % or em). This prevents an unusual jQuery bug where it jumps/skips when the accordion is sliding down (right when it reaches the bottom). I’ve researched this and some suggested specifying a height with jQuery, but I found my solution to be much more simple and effective. - Add padding to the nested
divin the.acc_container. This prevents another bug where the padding is animated when the accordion is in opening/closing.
h2.acc_trigger {
padding: 0; margin: 0 0 5px 0;
background: url(h2_trigger_a.gif) no-repeat;
height: 46px; line-height: 46px;
width: 500px;
font-size: 2em;
font-weight: normal;
float: left;
}
h2.acc_trigger a {
color: #fff;
text-decoration: none;
display: block;
padding: 0 0 0 50px;
}
h2.acc_trigger a:hover {
color: #ccc;
}
h2.active {background-position: left bottom;}
.acc_container {
margin: 0 0 5px; padding: 0;
overflow: hidden;
font-size: 1.2em;
width: 500px;
clear: both;
background: #f0f0f0;
border: 1px solid #d6d6d6;
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-moz-border-radius-bottomleft: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
.acc_container .block {
padding: 20px;
}
Step 3. Setting up jQuery
For those who are not familiar with jQuery, do check out their site first and get an overview of how it works. I’ve shared a few tricks that I have picked up along the way, you can check those out as well.
Initial Step – Call the jQuery file
You can choose to download the file from the jQuery site, or you can use this one hosted on Google.
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.1/jquery.min.js"></script>
Directly after the line where you called your jQuery, start a new <script> tag and start your code by using the $(document).ready event. This allows your jQuery code to run the instant the DOM is ready to be manipulated. The code you will be writing in the next few steps will all take place within.
$(document).ready(function() {
//Code goes here
});
Bringing it to Life – jQuery
The following script contains comments explaining which jQuery actions are being performed.
//Set default open/close settings $('.acc_container').hide(); //Hide/close all containers $('.acc_trigger:first').addClass('active').next().show(); //Add "active" class to first trigger, then show/open the immediate next container //On Click $('.acc_trigger').click(function(){ if( $(this).next().is(':hidden') ) { //If immediate next container is closed... $('.acc_trigger').removeClass('active').next().slideUp(); //Remove all "active" state and slide up the immediate next container $(this).toggleClass('active').next().slideDown(); //Add "active" state to clicked trigger and slide down the immediate next container } return false; //Prevent the browser jump to the link anchor });
The Logic – What’s Happening Here?
- First set the default settings: Open first accordion and add active state.
- On click: Find out if the clicked accordion item is opened or closed.
- If clicked item is “hidden” (closed) then…
- On all accordion items – Remove all “active” classes and slide up (close) all immediate next
.acc_container. - On clicked trigger
$(this)– Add “active” state and slide down the immediate next.acc_container.
Related Articles Elsewhere
Related Posts
Author Bio
My name is Soh Tanaka and I am a Los Angeles based designer/front-end developer specializing in CSS driven web design with an emphasis on usability and search engine optimization. I also run a CSS Gallery which is updated daily with the best CSS websites from around the world. Come check it out!
You can learn more about me or
Follow me on twitter for more updates and resources!
Did You Enjoy This Post?
Subscribe via RSS or by email to get all upcoming tutorials and articles delivered straight to you.






+ Add Comment83 Peeps Have Spoken Their Minds...
Your site is da bomb and your side scroll bar… brilliant! Thanks for sharing your smooth accordion, one of the best I have seen.
Once again, another great peice of jquery to use in any projects. Visiting often and always waiting for the next post.
As usual, you don’t dissappoint. Thanks for a great article.
Awesome, thanks bro!
Awesome post, as usual.
And nice job on the site redesign!
Great post. I have been looking something like this for a while. Thank you for uploading such great quality tutorials.
Awesome. Easy to follow! Will be using this on my site. =) Thank you
Nice solid tutorial… seems relatively simple but highly effective…thanks..
I’m curious, which plugin (if any) did you use for code examples?
Btw, great and useful tutorial. Use it already :D
@Michael, I actually didn’t use any plugins for this. Just your typical
pretags, and some jQuery to animate it to expand :-)This is what i like the most, the simplicity but the power of a few lines of code, not everyone can achieve this of course.
Nice desing.
Love it. Thank you.
Simple, clean and effective! This is a cool tut thanks.
Nice Deigns :) Thanks
Smooth sliding, great looking accordion. Thanks so much for this tutorial.
Great simple toggle.
Is there any way to force only one toggle open at a time?
@Jason – http://www.sohtanaka.com/web-design/easy-toggle-jquery-tutorial/
Awesome, love it! Also, I noticed something is whacky with your Simple Tabs tutorial in Google Chrome, works great in IE and FF, but for some reason the first tab’s content isn’t appearing when the page loads, you have to click on a tab to get the content to load. Once loaded you can move from tab to tab as expected, but a refresh clears the tab content and again your just looking at the tabs themselves! I tried both dev and release versions of Chrome. Any ideas? Thanks.
@Hank Thanks! That is strange, my chrome seems to be showing the first tab and it’s content fine.
@SOH hmm… This is frustrating! I’m using 5.0.396.0 So weird, I’ve tried on both my work and home PCs. Using dev tools I’ve narrowed down the problem to Chrome not styling the tab_content for with the appropriate “display: block;” CSS. Instead it stays “display: none;” In IE and Firefox it gets the appropriate inline styling. I’ve linked some screen shots: http://picasaweb.google.com/lh/photo/ie66Pd9qJvoe5jfIc2PEZQ?feat=directlink
http://picasaweb.google.com/lh/photo/OOHoXFKRZ6mt7CFWU0jMHQ?feat=directlink Maybe I’m just crazy, but this issue has been driving me nuts! Thanks again, your tutorials are awesome!
good code, thank you for you share
@SOH, thanQ for the quick answer. Like the idea of the code examples expanding.
Hi,
I love this! I am having a problem however (IE of course!) This looks great in other browsers, but in IE, the accordion behaves as though it’s in a wrapper and sits center stage, moving as though I have a wrapper on the body. I have the entire accordion housed in a div which is position:absolute. Is there a workaround for IE? Or, do you have any suggestions? The site is not live, but on my server so I can test it.
MIM
@MARIANNE Does this happen on the demo? I’ve checked in all versions of IE and it seems to be working correctly for me.
Hi,
No, it doesn’t happen on the demo. In the demo, the accordion is in the center of the page. On my page I have it on the left – but in IE it appears in the center.
In the event you didn’t see my URL, the site can be viewed here (I think I accidentally sent you the link from my local machine):
http://www.designbymarianne.com/CHINMAN_LARGER_SITE/index.html
Marianne
Not to be rude here on Soh’s blog but I can clearly see why he puts a disclaimer
“Please note: This tutorial requires basic knowledge of CSS and jQuery. For best results, please be sure to learn the proper foundations before attempting to take this tutorial. Learn one step at a time :-)”
because there are so many people who take these tutorials without knowing anything about css or js. Marianne do you know what margin: 0 auto; does? It centers things. So if you want it on the left you should float: left. You should really go back and learn CSS before learning more advanced things.
To ‘some guy who ‘cares’:
Yep, pretty rude. I tried that and it didn’t work. How much do YOU know? Clearly nothing about keeping quiet if you’re not the one being asked for some assistance. It’s funny, some people really need to feel ‘big’ by making assumptions and tossing insults. Shame. I notice you’re anonymous, big surprise. Please don’t ruin this site for people. If he can’t, or doesn’t have the time to provide insight beyond what you have attempted that’s fine, but your post adds nothing.
good,i like it
Good simple toggle.
thank you for you share !!!!!!! :)
hi soh…
what’s the font you use for the on of ur sub header.
such the one of the comment form. “SPEAKYOURMIND”
It looks cool.. hope you’d like to share…
thx
Wow pretty amazing what you have done to your new site.. Great layout and everything! Keep it up! :)
- iMediaGFX -
Sorry but can’t help to add. WOW (@ your floating nav menu) *Two Thumbs Up*
Great stuff!
How can i do this though?
I want to have all the items closed by default until clicked, at the moment i have the first content slider open, but wish for them all to be closed?
Thanks
Just brilliant. Awesome tutorial. Here is one of the templates where I have used it.
http://wantedtemplate.blogspot.com/ (sidebar)
Yes, it is hosted on blogger. This just goes to show how brilliant is the man who explained it so well that I flawlessly implemented on blogger.
Loved the post.
I am taking the liberty of adding a reference to your article on my CSS aggregator site. Do let me know if you are ok with this.
Very nice! I’m curious: is there a straightforward way to set the default open block to be other than the first one?
its great…please i need one tab action….its not closed in a open single tab…..can give me a solution
It’s… It just… The fact is…. MAN!… f*(k! YOU RULE! It’s awesome! Thanks!
Figured it out. In the jquery calls replace:
$(‘.acc_trigger:first’).addClass(‘active’).next().show();
with (to display the second block open by default):
$(‘.acc_trigger::nth(1)’).addClass(‘active’).next().show();
Replace 1 with 2 for the third block, and so on (it’s zero indexed). Just had to poke through the jquery code a bit to see what functions were defined. Cool stuff!
Oh, the “::” is a typo, but it will still work. It’s supposed to be just “:”
Martyn, to answer your question, just remove this jquery call:
$(‘.acc_trigger:first’).addClass(‘active’).next().show(); //Add “active” class to first trigger, then show/open the immediate next container
All blocks will start out hidden because of this previous line:
$(‘.acc_container’).hide(); //Hide/close all containers
anyone can help? how to create a multiple accordion in the same page? em trying to put accordion to multiple DIV content..
Thanks for this great Tutorial it came in very handy for a noob like me your
also i needed to m make the accordion tabs liquid so they wood stretch across the with of the page, with one of your other tutorials (Liquid & Color Adjustable CSS Buttons) i was able to accomplish this task.
for the person above me if you want to to put multiple accordions in the same page all you have to do is put this html
Web Design & Development
code in what ever div you want at least this is how it worked for me.
once again thank you for your tutorials they are real helpful
Dude you have some awesome designs. You’re my hero. haha
If you have a ton of content inside each accordion, how do you make it so when you open them the focus stays on the top of the one you clicked rather than it opening halfway in the accordion and then you need to scroll up to get to the beginning of that particular one? Know what I mean? :)
Thank you for that tutorial
Hey!Awesome tutorial, its working just fine but I got a question, have u tried using this same accordion menu but with this extra add-on:?
The first link “Web Design & DEvelopment” if you click on it,it won’t hide unless you click on another link, is it possible to hide it ? so you can see only the main links without showing the content UNLESS u click on it?
Hope I explained myself
Thanks for the tutorial, really enjoyed it. Is there anyway I can activate each of the panels from a remote sub menu? I’m building a site at the moment that requires an accordion effect, but that in addition to the links in each title bar, the ability to operate the accordion from a seperate nav menu of the same headings. Any help appreciated.
Draco,
If you want to be able to hide active content by clicking on it, just add this code.
else {
$(this).next().slideUp()
}
right after before the return false statement.
Complete script looks like this for me
$(document).ready(function(){
//Set default open/close settings
$(‘.acc_container’).hide(); //Hide/close all containers
$(‘.acc_trigger:first’).addClass(‘active’).next().show(); //Add “active” class to first trigger, then show/open the immediate next container
//On Click
$(‘.acc_trigger’).click(function(){
if( $(this).next().is(‘:hidden’) ) { //If immediate next container is closed…
$(‘.acc_trigger’).removeClass(‘active’).next().slideUp(); //Remove all .acc_trigger classes and slide up the immediate next container
$(this).toggleClass(‘active’).next().slideDown(); //Add .acc_trigger class to clicked trigger and slide down the immediate next container
}
else {
$(this).next().slideUp()
}
return false; //Prevent the browser jump to the link anchor
});
});
thanks……! it’s relay use fool Accordion tabs ……….. Thank You Once-again
………………………:)
Hi, thanks for this tutorial !
Can someone tell me how to change the color of the “h2 tag” please ?
This is what i did to test :
h2.acc_trigger a {
color: black;
text-decoration: none;
display: block;
padding: 0 0 0 45px;
}
h2.acc_trigger a:hover {
color: yellow;
}
but it didn’t work. The “Web Design & Development” still have the dark grey color !
An idea ?
Hi Soh,
Man… I love your site! I haven’t even read this tut yet, just wanted to say how much I like your use of CSS sprites for your headers – nice!
OK, now I will go back and read this tut :~)
Keep up the GREAT work!
Thanks!
~ Jim
Please, someone can answer my question ?
hi everybody!
I did all the steps but i still have just a div with text but no accordion menu!
Someone please can help?
Thank you so much, it works for me :)
Now i’m trying to add some images
Peace
This is really helpful, learned a lot from it. Thanks a lot for sharing!
Thanks… great website design too!
I am pretty new to jQuery and learning how to use it – thanks for the great Tutorial. I was wondering if there was a way to modify the code to have all “accordions” closed by default (as opposed to having he first one forced open) without drastically modify the code… Thanks for any assistance you may be able to provide.
Cedric (or any of you other jQuery wizards),
I am using icons similar to those in the demo to identify that an accordion is open or closed. I tried using your fix, and it seems that the headings are now indeed closing on click, but the “arrow” is not changing orientation from “open” to “closed”. It only changes once I click on a different accordion header. Do you know if there is a solution for this?
Another great CSS3 tutorial, i like it!
Hi, best step by step tutorial. Cheers mate.
Just one question though. Where are you replacing the acc_trigger background image?
Because when you the acc_container is hidden it displays a “play button” icon. And when the acc_container is displayed, it displays an “upside down pyramid”.
Thanks.
HI, I LIKE THE EFFECT HOWEVER COULD YOU BE SO KIND AS O TELL US AND SHOW SPECIFICALLY WHAT EACH IMAGE LOOKS LIKE THAT IS IN THE CSS OTHERWISE IT LEAVES US GUESSING A BIT.
Mohamed Hassan, hope thiz helpz… h2.active {background-position: left bottom;}
Great tutorial… was finding the built-in accordion function transitions rather horrible. This solved it perfectly! Great work!
Do you think it could be possible to create this as a wordpress widget?
I’m not sure if this was already asked in the comments, I tried reading them all but there are a truckload.
Everything is working fine except when I maximize/minimize one of the blocks it makes the rest of my page (eg. footer) jump up a little bit with it.
I’m sure there is an easy fix to this I just can’t figure it out.
Thanks in advance!
Awesome article ! Thank you very much. Is it possible to share the code ? I tired down loading the page but it did not download all the images. And the blue play button on the accordion.
Thanks,
Ash
Great tutorial! Love it!
@ Ben Johns: I had the same issue, but resolved it.
Just add “removeClass(‘active’).” to the else statement so it reads as follows:
else {
$(this).removeClass(‘active’).next().slideUp()
}
Hope this helps!
Best vertical accordion out there……..and thanks for a great tutorial. Please how I can cross link the the panels. Is there any way to create a nav that control the accordion. Thanks for you help.
Can someone please reply to my question above?
My footer is moving when the boxes are opened. I can’t figure out how to stop this from shifting my page around.
Thanks!!
Thanks for fix on the skipping bug. That was driving me nuts (and I tried a fixed width everywhere but the container… doh!)
It works perfectly, thank you :)
This site is awesome!
Thank you very much!
WoW : this is funk :o OMG
Your site is an inspiration! Great content and tutorial. Really good way on explaining THE steps. Definitely bookmarking your site as one of the best. Thank you very much.
Thank you for your share!Everything is working fine except when I maximize/minimize one of the blocks it makes the rest of my page (eg. footer) jump up a little bit with it.
My footer is moving when the boxes are opened. I can’t figure out how to stop this from shifting my page around.
Thank you!
Excellent tutorial, thank-you so much!
One small question, how do i get 2 accordions working on the same page?
This is what i have… mind you i’m a noob at jquery so please be patient!
//Accordion Set default open/close settings
$(‘.acc_container, .acc_container2′).hide(); //Hide/close all containers
//On Click
$(‘.acc_trigger, .acc_trigger2′).click(function(){
if( $(this).next().is(‘:hidden’) ) { //If immediate next container is closed…
$(‘.acc_trigger, .acc_trigger2′).removeClass(‘active’).next().slideUp(); //Remove all .acc_trigger classes and slide up the immediate next container
$(this).toggleClass(‘active’).next().slideDown(); //Add .acc_trigger class to clicked trigger and slide down the immediate next container
}
else {
$(this).next().slideUp()
}
return false; //Prevent the browser jump to the link anchor
});
Obviously i have the .acc_trigger2 in my styleSheets and on the markup of the second accordion i’m wanting to display.
Ta
Jes
Thanks! This had greatly helped me set-up CSS.
I also like the way you set up the code!
Great Blog!
Thanks a million again!
It’s great tutorial and your technique is so cool.
Well done go ahead.
Hmm >..< I have done all same like your instruction..
Thanks for sharing this. We have made use of it on our website.
http://walkit.com/walking-events-and-tours/list-your-event/
Thank you for your share.
Speak Your Mind...