If you need to do a vertical accordion menu, your first shot will probably be checking jQuery UI or searching for a plugin. Although this will fix your problem, I think this is overkill in this case. An accordion is quite a simple task for that can be implemented in just a few lines of jQuery.
Note: Click here for a working example.
Why do I prefer this approach to a plugin? There are several good reasons:
Your page will load faster. Less code, less library, less plugins.
Your page will perform better. Less, more simple code means better performance.
It will work EXACTLY the way you want. Simple code, easy to understand, easy to modify to suit your needs.
This is your demo HTML. You have a DIV containing your accordion menu, some H2 tags (or whatever you prefer) and the content for every accordion tag packed in a DIV class=”content” tag. This is it:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>An accordion menu in five lines of jQuery</title>
<style type="text/css">
div#accordion {width: 400px;}
div.content {display: none;}
h2 {cursor: pointer;}
</style>
<script type="text/javascript"
src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js"></script>
</head>
<body>
<div id="accordion">
<h2>Ender meets Rackham</h2>
<div class="content">I am your enemy, the first one you've ever
had who was smarter than you.</div>
<h2>Ender on his enemies</h2>
<div class="content">In the moment when I truly understand my enemy,
understand him well enough to defeat him, then in that very moment
I also love him.</div>
<h2>Graff talking on Ender's freedom</h2>
<div class="content">As a species, we have evolved to survive.
And the way we do it is by straining and straining and, at last,
every few generations, giving birth to genius.</div>
</div>
</body>
</html>Notice the CSS: The display property for content divs is "none", as we want all them to be closed by default. Notice also the cursor property, as declaring something is clickable Javascript doesn't make the cursor to change. We need to specify it manually.
OK, now, how does an accordion menu behave? To summarize, when you click on a title, it unfolds itself, and at the same time all other opened sections are closed.
This is the magic:
<script type="text/javascript">
$(document).ready( function () {
$('div#accordion h2').click( function () {
$('div#accordion div.content').removeClass('open');
$(this).next().addClass('open').slideDown('slow');
$('div#accordion div.content:not(.open)').slideUp('fast');
} );
} );
</script>Pretty simple, isn't it? The mouse event, plus our code, plus the closing bracket, just five lines of code.
OK, you did it. There's no step three, but if you want to run the extra mile, you can make this script run faster.
The reason this script does not run as fast as it could is because it has to run some selectors on every click. We can't avoid that, but we can cache a part of the selector to save some CPU. How is that?
$(document).ready( function () {
accordionCache = $('div#accordion');
$('h2', accordionCache).click( function () {
$('div.content', accordionCache).removeClass('open');
$(this).next().addClass('open').slideDown('slow');
$('div.content:not(.open)', accordionCache).slideUp('fast');
} );
} );
As you can see, we are running a selector and saving it in a variable. Notice also the variable's name is not the same as the DIV's id attribute. Why is that? This is due to Internet Explorer own understanding of Javascript. You can't declare a variable already used by an id attribute in Internet Explorer, because it already exists as a DOM object, and it can't be overwritten. This is the classic and cryptic error message:
Object does not accept this property or method.
This is an Internet Explorer only error, and it actually means “you tried to declare an object that already existed and can't be overwriten, and then you tried to use it. FAIL”.
Other than that, you're done. Your script is faster, better, and still less than ten lines of jQuery code, including the closing brackets.
Great tutorial, I have altered the code a bit
$(document).ready( function () {
$('div#accordion h2').click( function () {
$('div#accordion div.content').removeClass('open');
$('div#accordion h2').removeClass('active');
$(this).addClass('active');
$(this).next().addClass('open').slideDown('fast');
$('div#accordion div.content:not(.open)').slideUp('fast');
} );
} );
That adds a extra class "active" so that the selected h2 turn to a different color
Regards
Andre
Thanks a lot, Andre.
How does one apply this code to an unordered list?
Just change the jQuery selectors to make them appropiate for your code.
thanks for your sharing,I use accordion menu on my website...
Andre: Thanks for this great little script. I can think of many ways to use this, but what jQuery code might I add that will invoke the accordions on mouseover (instead of click)?
Just change "click" by "mouseover".
Thank you for this script! I'm trying to figure out how to adjust it so that a user can click an href link and open a specific panel. What can I add to jQuery to make this possible?
thank you very much for this code. It gives me ability to modify and add to current css without disturbing anything else
Thanks both for visiting!
Madbirddesign, your question is quite easy. My code could be simplified to:
$('h2', accordionCache).click( function () { // Do something... } );It's up to you what you put in there. Something quite interesting is the INDEX() method and the EQ: selector. Combining them, you can do something like: "When clicking on first link, open first panel. When clicking on the second link, open the second panel... and so on.
Check here:
http://api.jquery.com/index/
great bit of code there.....thanks a lot....bt im trying to make the content appear on top of the menu clicked ,unlike the way it normally slides down...can u plz help me....thank u loads n lots....
Maybe you can control the position of the content via CSS?
Post new comment