Create a Simple, Intelligent Accordion Effect Using Prototype and Scriptaculous
In Javascript / AJAX by Brian Crescimanno
We've all seen the "accordion" type effect used on many Web 2.0 sites; however, many accordion scripts are heavy, make poor use of the libraries they are based on, and don't handle things like ensuring that the accordion maintains a consistent height. In this tutorial, we will use the Prototype and Scriptaculous libraries to create a lightweight, intelligent accordion.
Demo and Source Code
Step 1 - The Goal
Our objective is to create a lightweight accordion script based on the Prototype and Scriptaculous javascript libraries. The accordion should:- Allow an unlimited number of accordion panes
- Be completely styled by CSS
- Be Unobtrusive—users without javascript turned on should see all of your accordion content
- Be Light Weight—With relatively few lines of code; use event delegation to limit memory consumption.
- Support any kind of content within the accordion
- Ensure that when the content of each accordion pane changes, the height of the accordion remains constant to avoid the annoying "page bouncing" effect

Step 2 - Begin with Basic Markup
To begin, we will create some simple HTML markup for our accordion:<div id="test-accordion" class="accordion">
<div class="accordion-toggle">Toggle 1</div>
<div class="accordion-content">Content 1</div>
<div class="accordion-toggle">Toggle 2</div>
<div class="accordion-content">Content 2</div>
<div class="accordion-toggle">Toggle 3</div>
<div class="accordion-content">Content 3</div>
<div class="accordion-toggle">Toggle 4</div>
<div class="accordion-content">Content 4</div>
</div>
Step 3 - Add Some Style
Next, we need to add some style around our accordion to make it look like an accordion. To begin with, we'll do a first pass of basic styling and then add more when it's all working. There are also some additional styles that need to be included to ensure that the accordion will display correctly as it is animating.div#test-accordion{
margin: 10px;
border: 1px solid #aaa;}
div.accordion {
position: relative; /* required for bounding--works around a "peculiarity" in Prototype */
}
div.accordion-toggle{
position: relative; /* required for effect */
z-index: 10; /* required for effect */
background: #eee; /* required for effect--can be anything except "transparent" */
cursor: pointer;
}
div.accordion-toggle-active{
background: #fff;
}
div.accordion-content{
overflow: hidden; /* required for effect */
background: #aaa;
}
See the basic accordion with a simple stylesheet.
Step 4 - Create the Javascript Accordion Class
Prototype provides a wonderful framework for building classes in Javascript and we'll use that functionality to build our accordion class. This class will contain all the properties and methods of an accordion: the currently displayed pane, the contents of the accordion, methods to expand and contract panes, and event handler methods to define what happens when users take an action such as clicking. For now, we'll set up the basic structure of the class as well as all the properties and methods we'll need:var Accordion = Class.create({
initialize: function(){
this.accordion = null; /* Stores a pointer to the the accordion element */
this.contents = null; /* Array of pointers to the headings and content panes of the accordion */
this.options = null; /* Allows user to define the names of the css classes */
this.maxHeight = 0; /* Stores the height of the tallest content pane */
this.current = null; /* Stores a pointer to the currently expanded content pane */
this.toExpand = null; /* Stores a pointer to the content pane to expand when a user clicks */
this.isAnimating = false; /* Keeps track of whether or not animation is currently running */
},
checkMaxHeight: function(){}, /* Determines the height of the tallest content pane */
initialHide: function(){}, /* Hides the panes which are not displayed by default */
attachInitialMaxHeight: function(){}, /* Ensures that the height of the first content pane matches the tallest */
expand: function(el){}, /* Tells the animation function which elements to animate */
animate: function(){}, /* Performs the actual animation of the accordion effect */
handleClick: function(e){} /* Determine where a user has clicked and act based on that click */
});
These are the basic methods and properties that we will need when building our accordion. Each of the next steps will
take you through building each method until we have a working accordion. If at any point during the tutorial you need
a quick refresher on what each method or property is for, you may use this heavily commented code as a reference.
Step 5 - Initialize: Get Things Started
Prototype classes have a special method called initalize() which is a constructor; this means it acts when the user creates a new instance object of that class. For any accordion, we need to know 2 things before we begin:- The id of the accordion element.
- The default starting position of the accordion (if anything other than the first position)
- Retrieve and store the accordion and its contents as pointers to those elements
- Set the user defined options
- Set the current expanded element
- Determine the maximum height we will use as the height for all of our content panes and apply it
- Hide the content panes which are not shown by default
- Add an event listener to the accordion to watch user clicks.
initialize: function(id, defaultExpandedCount) {
if(!$(id)) throw("Attempted to initalize accordion with id: "+ id + " which was not found.");
this.accordion = $(id);
this.options = {
toggleClass: "accordion-toggle",
toggleActive: "accordion-toggle-active",
contentClass: "accordion-content"
}
this.contents = this.accordion.select('div.'+this.options.contentClass);
this.isAnimating = false;
this.maxHeight = 0;
this.current = defaultExpandedCount ? this.contents[defaultExpandedCount-1] : this.contents[0];
this.toExpand = null;
this.checkMaxHeight();
this.initialHide();
this.attachInitialMaxHeight();
var clickHandler = this.clickHandler.bindAsEventListener(this);
this.accordion.observe('click', clickHandler);
}
As you can see, we've set all of our properties to reasonable default values and called 3 methods to help get things set
up. Finally, we've attached the event handler to the accordion. Let's create those three methods and the event handler.
Step 6 - Checking the Tallest Element
One of the requirements for our accordion is that it must scale so that even when the tallest content pane is expanded, the overall accordion height will remain constant. To accomplish this goal, we will iterate through the content panes determining which one is the tallest and set the maxHeight property accordingly:checkMaxHeight: function() {
for(var i=0; i<this.contents.length; i++) {
if(this.contents[i].getHeight() > this.maxHeight) {
this.maxHeight = this.contents[i].getHeight();
}
}
}
Step 7 - Hiding the Rest
Our accordion should only display the content pane specified as the current pane; all others should be hidden by default. Additionally, we need to set these content pane's height attribute to 0; this prevents the content pane from briefly appearing fully expanded before properly animating.initialHide: function(){
for(var i=0; i<this.contents.length; i++){
if(this.contents[i] != this.current) {
this.contents[i].hide();
this.contents[i].setStyle({height: 0});
}
}
}
Step 8 - Show the Default Content Pane
Now that we've hidden all but the default content pane, we need to make sure the default content pane displays correctly; it's heading should have the "active" style applied to it and it's height should match the maxHeight property:attachInitialMaxHeight: function() {
this.current.previous('div.'+this.options.toggleClass).addClassName(this.options.toggleActive);
if(this.current.getHeight() != this.maxHeight) this.current.setStyle({height: this.maxHeight+"px"});
}
Step 9 - Create the Event Handler
If you come from a traditional event handling background where we attach the event handler to each area we want clickable, it may seem confusing that we are only attaching the handler to one element. We are using event delegation. For those of you unfamiliar with the subject, I have written a brief overview of event delegation which will introduce you to the concept and why it is so important. That said, we need an intelligent event handler:clickHandler: function(e) {
var el = e.element();
if(el.hasClassName(this.options.toggleClass) && !this.isAnimating) {
this.expand(el);
}
}
There are two parts to this function. First, we determine what was clicked. Then, we check to make sure that it was a
heading that was clicked and that no animation is currently running. If this is the case, we call the expand() method
to start the process of the accordion. The variable we pass to the expand() method is the heading on which the user clicked.
Step 10 - Start the Process
Now we can start the process of doing the accordion effect. We know the expand() method must take a parameter for the element which was clicked. Using that parameter, the expand method determines which content pane to expand, and if it is not already expanded, calls the animate() method to "do its magic!"expand: function(el) {
this.toExpand = el.next('div.'+this.options.contentClass);
if(this.current != this.toExpand){
this.toExpand.show();
this.animate();
}
},
Step 11 - Doing the "Dirty Work"
At this point, all of the pieces are in place; we know which content pane is currently displayed, we know which heading the user has clicked, and we know which content pane the user has requested to be shown. Now, we must create the accordion animation. For this, we will create an animate() method that will use the Scriptaculous Effect.Parallel class to render the two animations together; and the Effect.Scale class to change the size of each content pane. The animate method will perform these steps:- Create an array that will be used to store our Effect.Scale objects
- Collect the parameters to pass to the Effect.Scale constructor for the content pane that will be shown and create the object
- Add that object to our array
- Collect the parameters to pass to the Effect.Scale constructor for the content pane that will be hidden and create the object
- Add that object to our array
- Create the Effect.Parallel object that will run our Effect.Scale objects is sync.
- Tell our Accordion object that we are animating
- Run the animations
- Clean up any styles left behind
- Tell our Accordion object that we are finished animating
animate: function() {
var effects = new Array();
var options = {
sync: true,
scaleFrom: 0,
scaleContent: false,
transition: Effect.Transitions.sinoidal,
scaleMode: {
originalHeight: this.maxHeight,
originalWidth: this.accordion.getWidth()
},
scaleX: false,
scaleY: true
};
effects.push(new Effect.Scale(this.toExpand, 100, options));
options = {
sync: true,
scaleContent: false,
transition: Effect.Transitions.sinoidal,
scaleX: false,
scaleY: true
};
effects.push(new Effect.Scale(this.current, 0, options));
new Effect.Parallel(effects, {
duration: 0.5,
fps: 35,
queue: {
position: 'end',
scope: 'accordion'
},
beforeStart: function() {
this.isAnimating = true;
this.current.previous('div.'+this.options.toggleClass).removeClassName(this.options.toggleActive);
this.toExpand.previous('div.'+this.options.toggleClass).addClassName(this.options.toggleActive);
}.bind(this),
afterFinish: function() {
this.current.hide();
this.toExpand.setStyle({ height: this.maxHeight+"px" });
this.current = this.toExpand;
this.isAnimating = false;
}.bind(this)
});
}
For a complete explanation of the option parameters we are passing to both the Effect.Scale and Effect.Parallel objects,
please see the Scriptaculous documentation.
The important aspects of the method are the beforeStart and afterFinish methods on our Effect.Parallel. The beforeStart
method tells the accordion that it is currently animating. This will prevent the event handler from attempting to start
any further changes so long as the animation is in progress. It also makes sure that the heading which was clicked is
given the "active" class name. The afterFinish method completely hides the content pane which had been previously displayed
(after it has disappeared due to the animation). It also ensures that the final height of the newly displayed content
pane is correct. Now that the swap is complete, it tells our accordion that the currently expanded content pane is the
one we have newly expanded and that the animation is complete.
Step 12 - Adding Some More Style
At this point we have a decent looking accordion, which you can see in action here. But with a little CSS we can make it all look much more spectactular. So first we create a quick Photoshop mockup so we have a rough idea of how it should all look. With that in mind, we're going to need three images:- A 'logo' image -

- A couple of nice background images -
and 
body {
padding: 130px 50px 50px 50px;
background: #252422 url(../img/logo.gif) no-repeat;
background-position: 60px 40px;
font-family: "Lucida Grande", "Lucida Sans Unicode", Arial, Sans-serif;
font-size: 11px;
line-height: 18px;
}
div#test-accordion{
border: 1px solid #343230;
background-color: #21201f;
padding: 10px;
}
div.accordion {
position: relative; /* required for bounding */http://nettuts.com/wp-admin/users.php
width: 800px;
}
div.accordion-toggle{
position: relative; /* required for effect */
z-index: 10; /* required for effect */
background: #3f3c38 url(../img/off.jpg) repeat-x;
background-position: bottom;
color: #fff;
cursor: pointer;
margin-bottom: 1px;
padding: 9px 14px 6px 14px;
border-top: 1px solid #5d5852;
}
div.accordion-toggle:hover, div.accordion-toggle-active{
background-image: url(../img/on.jpg);
background-color: #6d493a;
border-top: 1px solid #a06b55;
}
div.accordion-content{
overflow: hidden; /* required for effect */
background: #302e2c;
color: #c4bab1;
border-bottom: 1px solid #000;
}
div.accordion-content p{
margin: 9px 24px 6px 24px;
}
As you can see here we've:
- Added some background styles around the page and the accordion class
- Given the accordion-toggle div a regular background color
- Set the accordion-toggle:hover and the active states to use the same reddish background
Step 13 - See It in Action





Noura Yehia
June 11th, 2008
Very interesting tutorial.
Thanks for posting, and let’s hope we have more like this one.
Alex Willcocks
June 11th, 2008
Bit jerky in FF, XP when you initially click a link, most likely due to margins set in the CSS - they seem to produce this effect - should stick to padding.
kailoon
June 11th, 2008
you know what? Every time the tutorials here are having some nice layout. They seem to be a standard layout for nettuts’s tutorials, which is great!
Ben Griffiths
June 11th, 2008
These tutorials get better and better, thanks!
Simon North
June 11th, 2008
Neat tutorial, nice and simple to follow and the final outcome looks very professional, cheers!
Joefrey Mahusay
June 11th, 2008
Very interesting keep posting great tutorials. Thanks guys.
Lamin Barrow
June 11th, 2008
Very nice effect but i don’t think i it is worth the 8 javascript files with the total combined weight of 130kb you have to download. It’s just one of those things that contribute to a poor user experience.
Adam Griffiths
June 11th, 2008
Just a little note, you should use instead of - it’s valid and is good coding practice.
The end effect looks good, thanks.
yamaniac
June 11th, 2008
good job! Bit jerky in Safari! works nicely in FF and IE but as Lamin Barrow has said, it would be more cooler if we could have less number of JS files hangin abobe those head tags!!! Keep em comin you doin a great job!
Daniel
June 11th, 2008
very nice tutorial, thanks for sharing.
Danny
June 11th, 2008
Awesome tutorial, very useful
Adam
June 11th, 2008
Yeah, i agree with Alex, Its also very jerky in Safari too :S
still, amazing little tutorial
thanks again
Andrew
June 11th, 2008
Overall nice tutorial. The effect in Firefox is a tad buggy and doesn’t work how I expected, not sure if this is just me.
Adam
June 11th, 2008
It seems a bit jerky in Firefox. This usually occurs when animated due to the way you pad out the inner content.
The quick solution for this is to put an inner container around your content “” and pad that instead.
Brian Crescimanno
June 11th, 2008
Hi folks,
Given my time constraints, the NETTUTS crew offered to create a slick style to go along with the accordion and it seems to have bungled the effect up just a bit to where it’s jumping. I will edit later today (I’m literally about to step out the door to head to work) so that the effect is clean.
Glad people are enjoying the tutorial; I will respond to individual comments later today when I have time at the office or this evening when I am home.
George Burrell
June 11th, 2008
Strange, I have tried both the demo and downloaded the files, I don’t experience any issue with FF. Not sure if this is because I am runnning Vista?
Tom
June 11th, 2008
Nice tutorial and good looking result, but I don’t like so much the opening “jump”. Mootools accordion is definitely smoother
Andrew Pryde
June 11th, 2008
Loving it, keep up the good work!
Andrew
Mac Tyler
June 11th, 2008
I think this site should stick mainly to one javascript framework in its tutorials. Jquery is the best and can be used to do all of this stuff plus more. That is just my opinion.
Andrei Constantin
June 11th, 2008
Will check it ASAP
Collis Ta'eed
June 11th, 2008
Hey guys, as Brian mentioned, I added a little extra styling which seems to have made it more jerky, you can see the original minimal styling here - http://nettuts.s3.amazonaws.com/015_Accordion/accordion-unstyled.html - it is a lot smoother.
Hope I didn’t mess anything up with my extra css, I just couldn’t resist
Brian Crescimanno
June 11th, 2008
@Lamin Barrow
You bring up an interesting point about file sizes. Remember that minified and gzipped, these libraries are fall smaller to download. Additionally, with luck, they are not used for only one piece of your site. Libraries are meant for situations in which you will have many uses for–thus, distributing the weight.
@Mac Tyler
I’m sorry, I cannot agree at all with your post. First of all, this site is NETTUTS, not jQuery tuts. Second, your statement that “jQuery is the best” is a statement of opinion, not of fact. I do like jQuery a lot; however, when you’re working with a large website, that website will often choose (for various reasons) to standardize on one framework: that framework could be jQuery, but it could also be Prototype / Scriptaculous (especially if you’re using Ruby on Rails for the application framework). It could also be Mootools, Dojo, YUI, or ExtJS. To focus solely one one framework is a short-sighted approach. I happen to be a huge fan of both jQuery and Mootools, but my current employment requires me to use Prototype and Scriptaculous because that’s what we’ve standardized on. Never be afraid to broaden your horizons–especially where libraries and frameworks are concerned.
Brian Crescimanno
June 11th, 2008
No problem Collis, I will also work on your styling today and hopefully have the smoother version of the one you did (which I love, by the way) online later today.
inlikealion
June 11th, 2008
Once again, I’d LOVE it if Nettuts would PLEASE start putting a link to the demo at the top of all the tuts. It is a small thing that could greatly improve the user experience.
Thanks Collis & Co for all the hard work.
Tim
June 11th, 2008
Nice. but which is best? Scriptaculous, Mootools, jQuery, or Dreamweaver CS3 built in apps?
D. Carreira
June 11th, 2008
Another great tutorial…
I suggest to use another image to do an hover effect
I think with this, the tutorial will be perfect
Good work, thanks,
David Carreira
Lee McMullen
June 11th, 2008
Brian, I think this is an excellent tutorial and an excellent site (along with the sister PSDTuts site).
I was actually wondering just the other day if there would be any tutorials based on other JS frameworks. Therefore I was pleased to see this article popup in my feedreader today.
That said I also totally agree with your comments to Mac Tyler regarding different frameworks.
Keep up the good work,
Lee
Lee McMullen
June 11th, 2008
Also, regarding some comments about the number of files and hence file size:
AFAIK you only need to pull through the “effects.js” file along with prototype obviously (and maybe “controls.js” from memory) to get this to work. Which means you don’t need the slider.js/dragdrop.js etc files which are all currently being included on the demo page.
Therefore overall overall file size and server requests should be reduced hence slightly reducing page load time.
Brian Crescimanno
June 11th, 2008
@Tim,
It’s close to impossible to define which framework is best for building these types of rich interfaces. Each offers several strengths and weaknesses vs. the other options available. For example, Prototype is fairly tightly integrated with Ruby on Rails–so if you’re developing for the Rails platform, Prototype makes a lot of sense. Often you have legacy code to consider: if a site already makes heavy use of jQuery, it makes sense to stick with jQuery.
For Greenfield development over which you have complete control, evaluate each library on its own merits and rely less on hearsay and more on which library you feel meets your needs best.
aspa
June 11th, 2008
wow, people still use prototype?>
Shane
June 11th, 2008
Interesting tutorial, and the first if I’m right on this site to feature prototype/scriptaculous.
I played around with the libraries quite considerably on an ASP.NET project a year or so ago. I remember at the time that ASP.NET AJAX was still a bit buggy, so integrated prototype/scriptaculous in some ASP.NET controls.
I’ve just started another project, and I’m now using jQuery, because despite the maturing ASP.NET AJAX, jQuery is just so nice to use.
It’s a slight shame that the discussion has featured on jQuery vs. Prototype/Scriptaculous, when this tutorial itself is a good examination of what’s achievable with Prototype/Scriptaculous.
I guess comparisons are inevitable, and up to now, it’s been all jQuery.
Brian makes a good point - a lot of frameworks/libraries are out there - none of them is perfect, but having an awareness for the strengths and weaknesses allows you to make an informed decision about which one is right for you.
What amazes me is how far such things have come on in the last year or so, and how much easier it is to write stunning effects and integrate AJAX.
So - cheers to all the frameworks - exposure to as many as possible helps us learn to use them to their full potential.
Taylor Satula
June 11th, 2008
Its a bit jerkey in ff3 but good idea
Ali
June 11th, 2008
jQuery cut me off from web development, its too difficult.
something like this can be done in flash anyway. but good lengthy tutorial.
Chris
June 11th, 2008
Lamin is right, 8 JS files and 130KB is not worth the pretty effect.
Besides, you shouldn’t design your core user experience around JavaScript anyway. It’s poor practice.
Stefan
June 11th, 2008
Nice to see some variations in the frameworks.
…Maybe some mootools in the near future?
Brian Crescimanno
June 11th, 2008
@Ali–
I’m sorry you feel that way; with a solid foundation in object-oriented-programming, you’ll see jQuery for the impressive implementation it is. That said, I completely agree with what you said about Flash–though I feel that Flex is a better way to develop web applications using Flash Player as an environment.
@Chris–
Again, if you are in a professional environment, you will not send 130k down a pipe; these libraries would be at the very least gzipped which cuts down their size significantly. Furthermore, as I pointed out above, the idea of libraries is not so you can have ONE effect; it’s so you have reusable functionality that makes it easier to develop the *entirety* of your site.
As to you assertion that it’s “poor practice” to design your user experience around Javascript–are you telling me that Gmail is a poor user experience? Facebook is a poor user experience? Don’t confuse not having proper fallbacks with it being poor practice to design the best user experience possible given the constraints of the environment. Leveraging Javascript (or Flex) can provide a far richer, compelling, and friendly user experience than plain HTML. But remember: all good interfaces can be horribly abused (tabs anyone?)
Arun Stanislavose
June 11th, 2008
Sir
Great tutorial. I like the cool effect..But make sure that you make it smooth..its bit a jerky with the the images..
It looks very smooth here:
http://nettuts.s3.amazonaws.com/015_Accordion/accordion-unstyled.htm
Nico
June 11th, 2008
Pretty cool, thanks Brian.
Rijalul Fikri
June 11th, 2008
A very interesting tutorial, but I don’t know if I’m gonna use it someday. Because I don’t want to lose my focus because of learning multiple libraries. I’ve already used jquery as my Javascript library. Hope there will be more tutorial about it. Aside of that, this tutorial is wonderful.
Snorri3D
June 12th, 2008
a great tut and a nice effect was actualy looking for somthing like this for my self so thanks a lot for sharing
That would be great to have the smooth version as well that collis did if posible
Htoo Tay Zar
June 12th, 2008
Thanks a lot for this tutorial. I think i should read that js code carefully to understand that.
inlikealion
June 12th, 2008
Ok, did you guys add the demo link at the top after my previous post, or was I just really unobservant before? I’m sorry if it was there and I just hadn’t seen it. Either way, thanks for doing it - I find it easier to click an article and see the demo before I decide if reading the tutorial is something I want to spend time doing. Thanks a lot!
D. Carreira
June 12th, 2008
Now, I want a tutorial about EXT-JS…
Anyone wants to write one? I think thats could be a great tutorial!
David Carreira
Christian Mejia
June 12th, 2008
High Five Nettuts!
JPH
June 12th, 2008
How do you modify it to open on the first heading area instead of the second ?
lawrence
June 12th, 2008
Is there a way to set it up so that it starts at an initial size but resizes to a larger size if one of the ‘panes’ has larger content, resizing vertically only of course?
patience
June 12th, 2008
Love the tutorial.. I have been trying to figure this one out for a while… I checked it in FF and in IE… its a tad jerky but Its not a big deal… the only thing that I saw (maybe only my computer) but in FF when you click on another tab a vertical scroll bar pops up while the content is loading? Anyone else get that? None the less. I learned something new and I appreciate that the most. Thanks again Nettuts..
Chris
June 12th, 2008
@Brian Crescimanno: Your comments are quite correct. And in fact, your example does fall back well. Although it didn’t seem like it, which is my fault, that comment was directed more at the people that AREN’T experienced web developers - NETTUT’s core audience I’d imagine. The first thing I would do when using a library is remove the class functions I didn’t use and compress it, whether Gzip, minimizing, or both.
Regarding Facebook and Gmail - you have to design for your main audience. As I said before, I was addressing the developers reading this article, not your example. Gmail for the most part, and Facebook are designed for the “savvy-enough” users that have a modern browser, but aren’t worried about disabling JavaScript for “security reasons”. Even given the recent surge in XSS attacks, a user would quite possibly benefit more than be harmed by enabling it, (unless, of course, it’s your bank or other sensitive info).
Got off on a tangent there. Apologies. Anyway, sorry about the confusion.
Collis Ta'eed
June 12th, 2008
Hey all,
Brian has kindly fixed up a CSS error I made that was causing the jerkiness, view the demo
Sorry about that Brian, and thanks for fixing it up
Shane
June 12th, 2008
Thanks Collis and Brian for sorting out the CSS
Lee McMullen
June 13th, 2008
Hi Collis/Brian,
Just out of interest, what was the problem with the original CSS?
Thanks,
Lee
Brian Crescimanno
June 13th, 2008
There were two issues with the original CSS:
1) the accordion-content containers had top and bottom padding. Padding is not scaled; only height is, so as soon as the accordion-content containers would be shown, the padding would instantly show, causing the whole accordion to briefly appear taller than it should have been. I resolved this by using margins on the inner paragraphs rather than the accordion content itself; but you could also use a single inner div with a margin to create the same effect.
2) The second issue was that accordion-content had a border–which causes the same effect as the padding. Again, using an inner div and putting the border on it would solve the issue.
parsonh
June 13th, 2008
i wondered if there is away of adding a button that lets you expand or collapse? nice tut:)
Lee McMullen
June 13th, 2008
Thanks for that Brian, very useful.
@Lamin & Chris:
Regarding your earlier comments about file size, I’ve just tested and this accordion works with only prototype.js and effects.js pulled through. The combined file size works out about 38KB before minification which I personally think isn’t too bad.
Sean
June 13th, 2008
Designing with JavaScript integrated into the main design is not bad practice in itself. You can make a web-site have features that look so much nicer with JS effects. And there’s those people with JavaScript turned off, and actual good practice is making sure they still recieve an accessible experience.
So the deal with JavaScript, is to make your site look AWESOME, and then turn it off, and make sure everything still works without all the animated Ajax goodness.
Robin
June 13th, 2008
Hey fellas. This may be worth a post itself, but there’s been a lot of banter about doing the same type of effect in JQuery and there’s a top-notch blog out there called “Web Designer Wall” and it has a JQuery section called “JQuery for Designers”. In that post is some killer stuff, including simple implementations of accordion-like effects.
Enjoy!
Lamin Barrow
June 13th, 2008
I am agreeing with you robin, i have seen that tut a couple of months ago and WOW i was really impressed.
Jerry
June 14th, 2008
Great tutorial! I am XHTML/CSS designer by trade with growing knowledge of JS and have a question - how can I have the default position of all accordion elements be “closed” on page load or have the first panel be open instead of the second. Much Thanks!
Jaswinder Virdee
June 14th, 2008
Why have we got tutorials on jguery and then tutorials on prototype i think the site should be consistant in their use of javascript my vote goes towards jquery as it has a variety of plugins. Nevertheless another good tutorial, always impressed with the styling of generic components.
Gustavo
June 15th, 2008
Yeah, I agree NETTUTS should only go away from jQuery when it can’t perform something (which is almost impossible, but still…) It’s just like if we start to get FrontPage tutorials.
Welcome to Paradise
June 15th, 2008
This is superb. Accordion rocks. I was looking for just this. Thanks mate.
Banzaiaap
June 15th, 2008
First of all great tutorial!
I still have a question.. How do I change which tab is opened when I load up the page?
Thanks
Joefrey Mahusay
June 15th, 2008
We want some more great tutorial here in NETTUTS… Thanks guys!.
Jbcarey
June 16th, 2008
This is great!… really… great!
i know I’m gonna do this for my next portfolio….
Brian Crescimanno
June 16th, 2008
@parsonh
Sure, to add a button to expand or collapse, you’d simply need to add an event handler to that button that calls the accordion with the correct parameters to expand the one you want expanded.
@Jerry,
The accordion is designed to always have one element expanded. To have the first element expanded instead of the second, you can simply call the accordion constructor with the parameter of the position you wish to be open first, so it would look like: new Accordion(’id’, 1);
@Jaswinder, Gustavo, and others whose love of jQuery seems to border on fanboyish,
I have to ask: why only jQuery? Is it because those happened to be the first tutorials put on NETTUTS? I’m just trying to get a handle on what the criteria is for a library to be used in a tutorial on this site in your mind. If it was based on most widely adopted, we’d likely be seeing all YUI tutorials.
As I pointed out earlier, there are several great options of Javascript libraries to use–restricting yourself to one of them is foolish. I can guarantee, from personal experience and words of my peers who’ve had to do the same, you will eventually be forced to work with several different libraries. My advice is to be prepared to work with several of them–I’d hate to see anyone here have to turn down a good job offer because the job uses Prototype and not jQuery. As I also pointed out earlier, I have nothing against jQuery (in many ways, I like it more than any of the other popular libraries); but it frightens me to see this kind of “My library choice is the ONLY choice” mentality.
@everyone
Thanks for all the kind words about the tutorial; I hope many of you find it helpful. And I hope it helps you really explore what’s possible with Javascript now that you can see how something considered complex like an accordion is put together.
Johan Munk
June 16th, 2008
Man, This was just what i was looking for. Thanks so much
imaginepaolo
June 17th, 2008
Great! Really great!
Code It Red
June 17th, 2008
Thanks for the tutorial. It’s very hard to find some nice quality stuff like this and most of the documentation for some of the well known scripts aren’t so great in detailing how to properly utilize it. Will definitely be using some of this in my upcoming projects.
orchid
June 18th, 2008
Would it be possible to make this work horizontally as well? Or would the divs vertical stacking make it impossible?
jonms83
June 18th, 2008
is there a quick way to make it not a consistent height ?
adamn
June 18th, 2008
great tutorial guys! looking for the same request as above….a simple way to make the height not consistent so it doesn’t create too much space for sections with little content.
Toks
June 18th, 2008
How would you change the function to onRollOver rather that click
Sam
June 19th, 2008
Hi guys, just so you know the download link still contains the jerkyness.
I don’t get it, I scanned both css files as well as the html of the page, both are exactly the same, yet the online demo is not jerky, and the one you download is!
Could someone literally put up a changelog of what’s changed, or update the download link with the new files?
Also, would it be possible to tell me what exactly was wrong with the CSS. It’s these little things that sets a good and an expert designer apart.
Sam
June 21st, 2008
You realise using mootools 1.1x you can implement an accordion using:
window.addEvent(’domready’, function() {
//create our Accordion instance
var myAccordion = new Accordion($(’accordion’), ‘div.accordion-toggle’, ‘div.accordion-content’, {
opacity: false,
});
});
It does pretty much the same thing. What does this do that’s different?
Michael
June 22nd, 2008
Totally LOVE this accordion and went to replace the original Spry one I was using but not being a super clever programmer type run into something that’s forced me to go back to the Spry one…
1. Each window doesn’t adapt to the amount of content…so if the first tab has a bunch of content, and the second has less, you’ll have a second tab that’s got lots of dead space at the bottom.
That doesn’t both me nearly as much as this issue though…
2. When you resize text (I’m running Mac - not sure if this happens on Windows) the window doesn’t adapt to the resize, which is in itself not that bad if when you select another tab and then select back to the first, it’ll reload and readjust the size, but this doesn’t happen. You have to actually do an entire reload of the page which isn’t really acceptable I think to demand this of users…people tend to resize text on the fly? Or am I just being too demanding?
All things considered, I want to say a huge thank you to Brian and the NetTuts team for taking the time to post this fantastic detailed tutorial! Much appreciated!
All the best,
Michael
Sean
June 23rd, 2008
The code for this particular script looks remarkably like the code found here:
http://www.stickmanlabs.com/accordion/
It uses the same JS libraries, and allows for both vertical and horizontal accordions, as well as nested accordions.
William Frist
June 23rd, 2008
Re: jQuery vs. others js Frameworks ebate: Brian asks: “Why the fanboy love for jQuery? And why stick with one?”
This is how I would look at the questions:
1) I don’t think it’s unintelligent fanboyism. jQuery has some clear benefits that show it to be a better framework.
2) The most important factor: it’s more lightweight than other options when doing most things. That reason alone should be enough.
3) I’ll bet many environments that have chosen non-jquery frameworks have done it before jquery had gained steam - or for some other reason - and now consider themselves committed to a “legacy” js framework. That doesn’t mean a nettuts.com kind of site should promote a less-than-ideal framework.
4) You can have jquery apps running on a site with other libraries.
And why should nettuts.com stick with one framework?
1) It would be more helpful to users to promote (that’s partly what you are doing) and impart to viewers the best solution to a problem, I should think. The best solution to this particular nav issue I think would be to say: the goal is to create a slick accordian nav w/ js. Step 1) Which js framework should I use? Let’s see the quick pros and cons of my options. Oh look jquery requires my nav to only be X kb’s fat while the others require it to be Y kb’s fat… Even if the discussion is as simple as that single sentence..
2) Does Nettuts write tuts on the second, third or fourth best way to solve a problem? I don’t know, maybe it does. Are there tuts on here somewhere about how to create ASP or Cold Fusion sites?
pyemachine
June 24th, 2008
Great Tut. Love the style and the functionality. I notice though there is a gap between the Toggle titles in IE and Safari but in Firefox 3 they are bumped up together. Where can you control that?
keep up the good work.
Strajk
June 24th, 2008
Thanks, great tut… but at the beginning in class summary you have method named handleClick: function(e){} and then you use method clickHandler: function(e){}
All the best, Strajk
Strajk
June 24th, 2008
And pretty good way to fix the jerkiness with content padding is to add another class method which wrap content into another div (with margin set in css), so you don’t have to mess html code…
wrapContents: function() {
for(var i=0; i<this.contents.length; i++) {
this.contents[i].update(”+this.contents[i].innerHTML+”);
}
},
Raj Dash
June 24th, 2008
@Sean: I’m looking into this, but to me it appears that Brian has used the accordion.js created by Stickmanlabs and expanded upon the example. However we do take these things seriously and I’ll check with Brian.
Raj Dash
June 24th, 2008
@William: Personally, I prefer jQuery for pretty much the same reasons as you mentioned. However, as Editor of NETTUTS, I don’t want to completely cut off other choices.
Where do you draw the line at what gets accepted or not? Well, trends partly, and my own subjective view of what’s hot/ important right now. Maybe six months from now, some JS library will come out that beats the pants off jQuery. Does that mean I’ll stop accepting jQuery tutorials. Maybe. Maybe not. It’s not an easy decision to make.
Brian Crescimanno
June 24th, 2008
@Orchid–yes, I’m sure it would be possible with some modifications.
@jonMS83–Yes, you would need to comment out the use of the checkMaxHeight() method.
@Toks–Sure, have the clickHandler method set to observe “mouseover” instead of “click”
@Sam–The change is to remove any vertically oriented padding, margin, or border from the actual li elements that are the body of each accordion. Anything other than height will not animate properly and cause jerkiness.
@Sam–Yes, I realize that MooTools has a built in accordion. This tutorial was designed for the intrepid who want to learn how it all works.
@Michael–To address your first issue; one of the main goals of this accordion was to ensure that the accordion as a whole always took up a constant height. This will prevent the entire page from being moved / shifted when the accordion is switched. As to the second issue; I’m sure that could be considered a flaw in the code to not adapt immediately to font size changes, but I’m not sure whether or not you’re being overly demanding.
@Sean–The code that actually performs the animation is quite similar and yes, I had seen that code before writing this tutorial. Frankly; with scriptaculous, its a very clean implementation of how to handle this type of animation. However, this accordion does serveral things the stickmanlabs implementation does not–and vice versa. I assure you, there was never any intention to “rip off” another’s work and I apologize for any confusion.
@William–Thanks for your intelligent comments on the “jquery debate.” When I refer to “fanboyism” I refer only to people who immediately disregard this tutorial because its not based on their library. That said, there’s still merit in learning the core javascript techniques that the article also covers as well–and porting such an example to jQuery would be a fairly easy task for a reasonably skilled developer (should they want to try it). Frankly, as I’ve said many times, I also like jQuery; however, your assessment that all other frameworks should be considered “legacy” frameworks is a bit off the mark in my opinion. I also don’t see the matter of “jQuery is better” in nearly the black-and-white terms you do. I stand by my assessment that I’d hate to have to turn down a gig because I didn’t know how to comfortably work with THEIR Javascript framework.
@Strajk–Cool suggestion: I like it!
@Raj–Glad to hear that the site is looking to maintain its policy of openness on the tools used. In my opinion, it makes the site far more valuable to those looking to learn as much as they can.
Strajk
June 24th, 2008
@Sean: I’ve seen than script too. Few days ago I was trying to use it in my web but it is made to use with prototype 1.5 and it doesn’t work with latest version (1.6) - moreover it’s too complicated and complex to use with simple accordion effect… so I’m glad for this tut, it looks pretty cool on my web
source
June 25th, 2008
Very nice tut. even though you can use the built in SPRY assets in DW3 to do this.. but this is so much better.
Strajk
June 29th, 2008
Any idea how to expand clickHandler to elements that are descendants of the toggle div?
I need help to get it work with a DOM like this:
somethingsomething else
Braden Keith
June 30th, 2008
Now that that new one came out this one looks like crap. lol. but it is interesting to see the collapse.
I wish there was a fix to make it so it doesn’t loop if you keep clicking it really fast.
Hintz
July 3rd, 2008
is there a way that at the beginnig nothing is active (all accordions are closed)?
Shawn Johnston
July 4th, 2008
@Brian
You told jonMS83 to comment out the checkmaxheight function. Doing this renders all divs un-slideable if you know what I’m saying. I love this function and this is the first tutorial that has actually made it customizable and understandable to those of us who use javascript in our sites without actually knowing how to write it from scratch.
Could you be a bit more specific on what would need to change in order to deactivate the maxheight? I’ve got one div that’s quite long and it’s making the other much shorter divs way to big.
Thanks in advance!
JBiz
July 9th, 2008
I commented out the checkmaxheight function, and the accordion shows up correctly, but then when I click a different tab, all of the content with the accordion-content classes goes away leaving only the content with the accordion-toggle classes. My problem may be similar to Shawn’s post above, I just didn’t quite understand what he was saying.
skipwalker
July 10th, 2008
@Hintz
Simple (and not too sexy) method for having all accordions “closed” is to add one at the bottom that has no content following it. The bottom element should then be called in the accordion constructor (whatever the id number it is).
Miller
July 17th, 2008