JQuery Accordion menu
This post is here for historical / archival purposes. Comments are disabled. Please visit the link below for the latest version of the JQuery accordion.
This weekend I did a simple Accordion menu using JQuery. I figured it would be nice to share it on my blog as it may be useful to other people. I have no idea if this has already been done, if someone else has done a better job at it but... this one is mine! Feel free to use it if you need an unobtrusive Javascript accordion component on your (non commercial) website.
I whipped up a little demo page where you can see the menu in action and download the source. The menu will open with the first submenu expanded and items that don't contain a submenu will behave like regular links.
I didn't think I'd need to make this remark but: please don't be an asshole and do what these people from html.it did. Not with this, not with any of my other stuff, heck, not with anyone's stuff. It's just wrong. Thanks!
Source
function initMenu() {$('#pagemenu ul').hide();$('#pagemenu ul:first').show();$('#pagemenu li a').click(function() {var checkElement = $(this).next();if((checkElement.is('ul')) && (checkElement.is(':visible'))) {return false;}if((checkElement.is('ul')) && (!checkElement.is(':visible'))) {$('#pagemenu ul:visible').slideUp('normal');checkElement.slideDown('normal');return false;}});}$(document).ready(function() {initMenu();});
Go to the demo page to take a look and download it if you like it.
small update: I added a version that acts as a simple collapsing menu. Even less code needed for that:
function initMenu() {$('#menu ul').hide();$('#menu li a').click(function() {$(this).next().slideToggle('normal');});}$(document).ready(function() {initMenu();});
Safari 3 weirdness update
In the comments a problem with Safari was described. I just tried the example page in the latest nightly build of Webkit and it's working fine. I guess it's therefore safe to assume we're dealing with a Safari 3 bug.
Filed under: programming
Number of comments:
Number of trackbacks:
Tagged with: 







At 25 November '07 - 15:54 Max wrote:
At 25 November '07 - 16:00 Max wrote:
At 25 November '07 - 16:03 Marco wrote:
I’ll upgrade everything to something better when I move to PivotX I suppose. Or when I redesign… or… or…
At 25 November '07 - 21:08 hcabbos wrote:
At 26 November '07 - 00:53 Marco wrote:
Unfortunately I have no explanation for this as of yet.
At 26 November '07 - 00:58 bramn wrote:
So great work, I could use this for my blog redesign, if it will ever be finished :)
At 26 November '07 - 10:11 Rose wrote:
At 26 November '07 - 10:28 Marco wrote:
But then again the author states in the comments:
// I don’t care what you think about the file size…
I can see that ;)
At 27 November '07 - 02:59 Rose wrote:
) The one in your post is much better ;)At 27 November '07 - 06:09 Max wrote:
At 27 November '07 - 06:17 Marco wrote:
The menu on that site works fine in Safari. It must be some really odd edge case with this particular example page. Some true weirdness indeed. In addition, if you download the zip and load the example locally it ALSO works fine.
At 27 November '07 - 06:47 Max wrote:
Clicking in the URL bar and hitting enter brings stuff back the way it was.
In case you hadn’t already, I’d file a bug with the WebKit people. Edge case or not, ignoring inline style declarations shouldn’t happen.
At 28 November '07 - 10:30 dawei wrote:
Thanks/Dawei
At 28 November '07 - 12:05 marco@i-marco.nl wrote:
Change it into:
function initMenu() {
$(’#menu ul’).hide();
$(’#menu ul:first’).show().addClass(‘expanded’);
$(’#menu li a’).click(
function() {
var checkElement = $(this).next();
if((checkElement.is(‘ul’)) && (checkElement.is(’:visible’))) {
return false;
}
if((checkElement.is(‘ul’)) && (!checkElement.is(’:visible’))) {
$(’#menu ul:visible’).slideUp(‘normal’).removeClass(‘expanded’);
checkElement.slideDown(‘normal’).addClass(‘expanded’);
return false;
}
}
);
}
$(document).ready(function() {initMenu();});
This adds / removed a class=“expanded” to whatever is expanded.
At 29 November '07 - 03:34 dawei wrote:
$(’#menu div’).hide();
$(’#menu li h3’).click(
function() {
var checkElement = $(this).next();
var one = $(this);
if((checkElement.is(‘div’))
At 29 November '07 - 03:35 dawei wrote:
At 06 December '07 - 09:43 Jon wrote:
Thanks.
At 06 December '07 - 09:48 Marco wrote:
At 12 December '07 - 12:24 Trevor wrote:
is it possible to have the state saved between pages?
At 14 December '07 - 08:30 Marco wrote:
At 20 December '07 - 20:16 Aaron wrote:
At 02 January '08 - 06:26 Joerg wrote:
first: I am a german user. I excuse me for my bad English.
How can it be done to open the second Submenu at the initial sitecall?
At the first submenu you have the command: “$(’#menu ul:first’).show()”
but “$(’#menu ul:second’).show()” isn’t working!
It is necessary because there are some subs that require the second submenu opened.
At 16 January '08 - 03:50 javier wrote:
but only get one record of the subcategories…
Should I modify the code?
This is what I want:
MainCategory
– SubCat
– SubCat
But I get:
MainCategory
– SubCat
Here is my code:
———————————————————————-
At 06 February '08 - 04:56 MFD wrote:
How about this.
To find an element “activeMenuLink”
The branch containing this element should be opened at loading
Example
Thanks.
At 07 February '08 - 07:53 Charlie wrote:
Do you know a fix to support multi level (more then 3) accordion menu?
Or can it be done by your script?
At 20 February '08 - 03:37 Marco wrote:
@Joerg: Try $(’#menu ul:first’).next().show()
@Charlie I’m not entirely sure what you mean. Do you mean a menu with submenus that contain additional ‘sub-sub menus’ ?
If that’s what you mean then no, it can’t be done with this code. It would need to be modified.
At 28 February '08 - 23:08 prabhu wrote:
At the first submenu you have the command: “$(’#menu ul:first’).show()”
but “$(’#menu ul:second’).show()” isn’t working!
It is necessary because there are some subs that require the second submenu opened.
At 29 February '08 - 10:52 eenx wrote:
At 08 March '08 - 14:38 Bohonyi Balazs - Zsolt wrote:
Thank you !
At 14 March '08 - 08:24 cielosky wrote:
I’m wondering if there’s a way to close the open submenu list without refreshing the page.
I have adjusted the script so all submenus are initially closed:
$(’#menu ul:first’).hide();
But currently one submenu always remains open after a main menu item is clicked. I’m wondering if there’s a way that the submenu can close not only if you click on another main menu link, but also if you click on the link for the open submenu, closing all submenus?
It seems like this would be possible, but I’m only becoming familiar with scripting. Thanks for any assistance!
At 23 March '08 - 13:30 Colordrops wrote:
At 23 March '08 - 16:06 Marco wrote:
I respect your opinion and I happily invite you to write your own code if you have problems with my terms. I do the same!
After all, it’s just a couple of obvious lines right? So what are we talking about really?
At 24 March '08 - 01:02 Colordrops wrote:
http://www.learningjquery.com/2007/03/ac..
The reason for this coincidence is because your instantiation is basically the standard mechanism for creating an accordion tab using jQuery (in lieu of using an actual accordion widget). 95% of the work is already being done by jQuery and you are just putting the lego blocks together in the obvious fashion, and to somehow restrict this would be akin to restricting use of a particular instance of a “for loop”. It’s a standard UI element. Now if someone took both your style sheet and your code byte for byte I can see a case for you being upset, but if someone learned the basic structure of a jQuery accordion tab from your site and built a similar version, then i feel that there is no plagiarism occurring.
At 24 March '08 - 04:13 Marco wrote:
My original post was mostly about showing how to do a JQuery menu and not so much about ‘releasing a product’ or anything like that. I didn’t charge any money for anything either.
The whole copyright thing is more about people working on commercial sites, simply copy/pasting everything they can get their hands on and not at all about people who are trying to learn.
If someone independently writes something that ends up virtually the same as what I did then I suppose this person didn’t even need to read my post as they are clearly able to use JQuery correctly themselves
At 24 March '08 - 04:16 Marco wrote:
I do realise none of this is ‘rocket science’ or anything.
At 24 March '08 - 23:04 Colordrops wrote:
At 12 April '08 - 02:33 oscarml wrote:
when i use menu-collapsed.js instead of menu.js there’s a problem. When i click in an item to collpase/uncollpase it, the page scrolls up to the top. Do you know how to fix this?
bt the way, great job
thx
At 12 April '08 - 15:27 Marco wrote:
After the line that says:
$(this).next().slideToggle(‘normal’);
Add a line saying:
return false;
This will stop the link from being followed. My bad, this should have been in there from the start
At 13 April '08 - 03:12 oscarml wrote:
At 14 April '08 - 23:41 Martin wrote:
Great you reply on oscarml’s comment. I was reading this thread to find a solution to the scrolling prob.
Your work is great. Thanks again.
At 19 April '08 - 11:27 Christophe wrote:
How can I put an active link on the first list item :
Weblog Tools
PivotX
because the script
$(’#pagemenu li a’).click( ...
call the function but break the a href code.
Thank you in advance!
Christophe
At 21 April '08 - 12:00 m4c wrote:
Describe menu like this for ex.:
Weblog Tools
...
...and put before (for ex.):
function openMenu() {
$(’#menu ul.firstmenu’).show();
}
$(document).ready(function() {openMenu();});
That’s it!
At 22 April '08 - 03:03 Christophe wrote:
But I’m not sure I got well understood because my english is not as good as I wish.
I try again:
In your example : http://www.i-marco.nl/weblog/jquery-acco..
I’d like to put an active link on “Weblog Tools”, and the slide is already open, like in your example.
For the moment, the “a href” I put on this item is ignored because the script call the function on clic.
Thank you in advance !
At 25 April '08 - 02:19 Richard wrote:
Great bit of code which works really nice!
Just trying to get it working so a user could click on the open (expanded) item to close it again. I did notice that dawei posted something on this but I couldn’t get it to work for me. Any ideas?
Richard
At 29 April '08 - 02:06 Christophe wrote:
For people who may need to put an active link on the first , here it is :
function initMenu() {
$(’#menu1 ul’).hide();
$(’#menu1 ul:first’).show();
$(’#menu1 li a’).click(
function() {
document.location.href = $(this).attr(“href”);
var checkElement = $(this).next();
if((checkElement.is(‘ul’))
At 29 April '08 - 08:04 Jorn wrote:
Seems thats menu is expanded in that browser and does not function. Any ideas on how to make that work?
At 02 May '08 - 07:43 Adam wrote:
$(document).ready(function() {initMenusR();initMenusL();});
Any suggestions on how to use more than one accordion on the same page?
Thanks!
-Adam
At 02 May '08 - 08:58 Marco wrote:
You could change the code into this:
function initMenu(menuID) {
$(’#’ + menuID + ‘ ul’).hide();
$(’#’ + menuID + ‘ ul:first’).show();
$(’#’ + menuID + ‘ li a’).click(
function() {
var checkElement = $(this).next();
if((checkElement.is(‘ul’)) && (checkElement.is(’:visible’))) {
return false;
}
if((checkElement.is(‘ul’)) && (!checkElement.is(’:visible’))) {
$(’#’ + menuID + ‘ ul:visible’).slideUp(‘normal’);
checkElement.slideDown(‘normal’);
return false;
}
}
);
}
$(document).ready(function() {initMenu(‘menu’);initMenu(‘menu2’);});
At 02 May '08 - 09:00 Marco wrote:
At 08 May '08 - 18:29 Marco wrote:
After the feedback in the comments on this post I have more or less finished a new and improved version of this menu which allows multiple instances and some more new stuff.
I’ll be writing a new post about this soon and I’ll update this post with a link to the new entry as soon as it’s up.
At 08 May '08 - 20:13 Arun wrote:
At 09 May '08 - 05:53 sathish wrote:
Cheers
Sathish
At 22 May '08 - 22:25 Anzaan wrote:
That ensures my previous comment will never see the light of the day…
At 22 May '08 - 22:33 Anzaan wrote:
In a decent world all blog readers are treated decently and not like thieves out there to steal your few lines of JQUERY code.
Would you be kind to quell my curiosity and tell me what kind of world u live in,SIR ?
At 23 May '08 - 09:57 Marco wrote:
Can you please point out where I mistreat any blog reader like a thief? I fail to see it.
Also, a bit less prejudice in your attitude towards people you don’t know wouldn’t hurt you. Comments are moderated indeed but for the sole reason of spam prevention. I have never disallowed any legitimate comment on this blog. Not ever. Including comments that are of an insulting or derogatory nature.
My ‘few lines of JQUERY’ don’t need to be stolen by the way. They’re freely available. In case you were talking about my remark about html.it: If you read the post linked to in that remark you should be able to understand why that made me angry. If not, I’m sorry for you.
At 24 May '08 - 08:27 Anzaan wrote:
Marco buddy,
My sympathy goes out to you. I can’t even start comprehending the pain and suffering u must have gone through after discovering the shocking truth that your tutorial had been ripped off and used by some numbskull in a commercial project.
That dude that lifted your article and published it in commercial site should instantly be fired and blacklisted in global job market so he never gets reemployed anywhere in the world in the IT industry..
I see no such place for a numbskull like him in an elite industry of geeks, freaks and self-proclaimed gurus and pundits.
He proved his unworthiness by not following the industry’s fundamental must-must guideline of ‘ to err is human, to sin is human, but to get caught is plain fucking stupid’.
At 24 May '08 - 08:41 Anzaan wrote:
What makes it interseting is the fact that u wrote 10 lines of jquery code(.ahem..) , which is one way of doing what u did in jquery, and stamped your authority on it and classified a new species of living being called ASSHOLE at the same time.
Had JQuery only had GPL license and not MIT, it would have been interesting to discover that u marco my friend would have turned into one of the species u classified.
What was it , Asshole??
But of course u r a smart and highly moral super being ( I bet u go to church every sunday).
If u ever file a case against anyone for using your 10 line code assemble, if the defence lawer is worth his salt, he would tear u a new asshole through your hypocrisy in using free library to whip a 10 line ,oops again, 13 lines code and stamping authority over it….
“ If thy taketh (from jquery), thy should friggin giveth too sometimes (via ten line code, if nothing) ..... . “
Amen.
At 24 May '08 - 08:52 Anzaan wrote:
—————-
Marco my dear friend of recent days,
had u been a king of a country in those good old days,
u would have surrounded yourself with jesters to amuse u and to praise u all day.
If anyone dared say anything u didn’t like,
they would have been shot in front of live studio audience
I pray to the lord that doesn’t exist,
but wished the sucker actually existed at times like this,
to never let marco my dear friend be a ruler of his country by any mean.
If his censorship and ranting and evident self-love is anything to go by,
the poor citizens of the orwellian nation ,
of future ruler marco
if ever he ruled a nation,be very very afraid…......
very very afraid….
—————-
goodbye my friend of recent days…....
At 24 May '08 - 09:07 Anzaan wrote:
I forgot to give u parting advice as a dear friend.
How about u start dealing with things on per case basis, if someone nicks your sweat n tear , deal with them.
And if u want to publish things as demo or what ever, if u attach a license to your sweat n tear and just give a link to license such as MIT
Amen
At 24 May '08 - 09:24 Marco wrote:
Get over yourself man, seriously…
Taking someone elses work, ripping out credits and sticking ads in it for monetization is something I don’t like. It’s poor taste. It’s shit. No matter whether it’s a 10 lines demo or something big like my recent Pixelpost theme which tooks weeks to complete. No difference.
If you think it’s perfectly fine and I shouldn’t mention anything about it then that’s your problem.
Finally, I still fail to see the ‘censorship’ in any of my actions.
At 13 July '08 - 23:46 JCD wrote:
So, if you could help me, I’d really appreciate it. Thanks!
regs from mexico
jcd
At 16 September '08 - 11:49 Smith wrote:
For example if we want to use this menu for a web site with 300 pages, it would be really difficult to modify 300 pages code .
Thank you in advance
At 20 September '08 - 08:10 anang wrote:
At 02 October '08 - 23:05 tom wrote:
is it just my IE6 setting? (because someone up there said “I got it to work with IE6” so thinking I’m not alone?
At 03 October '08 - 01:05 Marco wrote:
I just tried that version in IE6 and it’s working fine for me.
At 09 October '08 - 23:07 Beta wrote:
IE 6 seems to extend the space between each menu tag !!
Can you please see what’s going on there !!??
http://yangbeta.oxyhost.com/test.html
thanks
Beta
At 23 October '08 - 04:02 Tom wrote:
I was hoping you might be able to quickly help me with a problem I urgently need to fix. I need to expand the second sub menu initially but the code you suggested to use in a previous post:
$(’#menu ul:first’).next().show();
does not work.
Any ideas?
Help will be greatly appreciated!
Tom
At 29 October '08 - 22:45 mariko wrote:
My English is so poor becouse I am Japanese.
I hope you understand my English.
I need to expand the second sub menu initially too.
I use ‘eq()’ and it is working.
$(’#menu ul:not(:eq(1))’).hide();
Try it.
At 05 November '08 - 04:58 Sebastian wrote:
————————————————————————————————
function initMenu() {
$(’#menu ul’).hide();
$(’#menu li a’).click(
function() {
var checkElement = $(this).next();
if((checkElement.is(‘ul’))
At 18 December '08 - 10:53 Joep wrote:
2 menu’s on one site doesn’t work. Also with the following code you gave Adam, Marco:
function initMenu(menuID) {
$(’#’ menuID ‘ ul’).hide();
$(’#’ menuID ‘ ul:first’).show();
$(’#’ menuID ‘ li a’).click(
function() {
var checkElement = $(this).next();
if((checkElement.is(‘ul’))
At 16 January '09 - 05:27 Joe Devito wrote:
First clickable element
Repeated as such, any help would truly be appretiated thanks
At 27 January '09 - 13:40 Drew wrote:
http://www.colostate.edu/Depts/Econ/new/
I’m fairly green at all this and found a few posts related to this, but have yet to figure out why the cookie for the menu is working in such a zany fashion on all but Firefox Mac. Any held would be awesome. Thanks.
At 28 January '09 - 11:57 Adam wrote:
At 10 February '09 - 13:56 Drew wrote:
At 23 February '09 - 07:36 ontelo wrote:
How could I add color to opened menu
So for ex. If I open Weblog Tools (from demo) its background would turn to yellow. And all opened itemes would be at the same way.
Maybe adding some .expanded class but how?
At 10 March '09 - 05:40 Thomas Alexander wrote:
At 19 March '09 - 18:30 Patrick wrote:
At 27 March '09 - 13:15 Chris wrote:
Any idea? Thank you.
At 26 April '09 - 19:01 Ronald wrote:
I tried it and works fine and also tried to integrate the newer version of JQuery works fine too. Thanks.
At 01 May '09 - 14:48 grace wrote:
At 01 May '09 - 19:28 MichaelU wrote:
Im a noob.
Thanks for the great menu.
At 21 May '09 - 04:48 Rajnikant wrote:
I have problem when I used this menu at 3rd level.
Help me urgent
Thanks for support in advance..
At 01 June '09 - 08:58 Arif wrote:
plz help me
At 22 June '09 - 10:15 Jordan Marcotte wrote:
But it would be nice if you include the images (icons) on the side. When its expanded, there would be a down icon, and when its collapsed, the opposite.
Any help?
At 25 June '09 - 10:49 Devi wrote:
Thanks
At 14 July '09 - 09:02 cathy wrote:
At 15 July '09 - 12:46 Ricardo Magalhães wrote:
Sorry my english.
At 20 July '09 - 21:30 sisir wrote:
i am using menu.js and jquery-1.2.1.min.js
please suggest how to fix it
At 21 September '09 - 11:40 Justin wrote:
Is there a way to keep the parent menu open after clicking an item with in the submenu to show the user where they are within the site?
I am trying to do this strictly with the java. I don’t want to have to add a class to the menu in the active or current page.
At 21 September '09 - 12:15 Ed wrote:
I am trying to make the expanded ul have a different background image and I saw where you modified the .js file to include an expanded class but I’m not sure how to implement that in my style.css file.
Also, when I use the modified code for menu.js (expanded class version) all my lists then become expanded, not sure why that is happening. Sorry for being so needy.
Thanks in advance for any suggestions you can offer.
At 07 October '09 - 04:31 Gurpreet Singh wrote:
$(’#menu ul’).hide();
$(’#menu li a’).click(
function() {
var checkElement = $(this).next();
if((checkElement.is(‘ul’))
At 17 November '09 - 11:31 mike wrote:
has anyone figured out the ‘mouseover’ functionality? i think i may have figured a small portion, but shit, small problems here and there are making that idea possibly wrong.
here is the code snippet:
function initMenu() {
$(’#menu ul’).hide();
$(’#menu li a’).mouseover(
function() {
$(this).next().slideToggle(‘slow’);
}
);
}
$(document).ready(function() {initMenu();});
hopefully someone can help, if not, cool too.
thanks,
mike
At 18 November '09 - 13:45 Stephen Johnston wrote:
I know there are countless other comments/questions about this, but how do you set a cookie for a second sub-menu?
Menu
— Submenu (when this menu is clicked)
—- Submenu (keep this menu open)
I am new to jQuery but I want to learn I just am a little frustrated at the moment and would like to know how to do this. I’ve been working on modifying lines all day with no avail.
At 03 January '10 - 07:22 yunshou wrote:
“$(’#menu ul:first’).show()”
TRY to
$(’#menu ul:eq(1)’).show();
At 03 January '10 - 15:10 Matts wrote:
In the beginning it’s fine, but they glue really together when they all slide in.
How is it possible to change this ? between the seperate menu’s is not that clear if you ask me.
At 07 January '10 - 19:23 klaas at yaki dot be wrote:
At 08 January '10 - 12:51 Alberto wrote:
best regards
Alberto
At 11 January '10 - 21:49 Geetha wrote:
At 21 January '10 - 05:48 Richard wrote:
Somebody mentioned php include. This is what I am currently trying to do. I am in the process of testing this menu out by splitting it into a menu.php file and including it into some very simple pages. I have it working but not fully.
The problem is by doing this it seems to break some of the functionality. Initially I noticed the top level menu items dont load the relevant pages when clicked. The child menu items do load the relevant pages but the menu returns to its collapsed state. I did do some nice customisaion to the menu using addClass / removeClass to help style the menu accordingly when sections were navigated to, but these are not currently working now because of the include. I tested it and found this particular part of the menu.js the problem:
var checkElement = $(this).next();
var parent = this.parentNode.parentNode.id;
Has anyone had any success doing this and / or can offer me any tips?
Thanks, Rich
At 28 January '10 - 04:13 Geoffrey wrote:
I need the tabs not to open so quickly and go beyond their borders.
At 03 February '10 - 12:19 dzieyzone wrote:
I just want to share with you some tweaks on the very nice accordion menu. This tweak will allow multiple level of submenu. here is my code:
function initMenus() {
$(‘ul.menu’).attr(“id”, “accordion”).addClass(‘noaccordion’);
$(’#accordion ul’).hide();
$(’#accordion .active-trail ul:first’).show();
$(’#accordion li.expanded a:first’).attr(‘href’,’#’);
$(‘ul.menu li a’).click(
function() {
var checkElement = $(this).next();
var parent = this.parentNode.parentNode.id;
if($(’#’ parent).hasClass(‘noaccordion’)
At 06 February '10 - 11:54 Ben wrote:
Adding the code through Magento, causes the top nav to stop responding. I presume that there is a java collision between the Magento and the jquery-1.2.1.min.js
Anybody seen this happen before? Peeking @ the jquery-1.2.1.min.js is hard work as it is serialised and quite un-readable.
Any ideas?
Thanks,
Ben
At 08 February '10 - 15:09 Seamoose wrote:
Can anyone help me implement this as I’m unsure where the function belongs in the js file.
Thanks
At 14 February '10 - 09:06 Stewart Amgwert wrote:
I’ve just found your jquery accordion menu and I like it a lot. Very easy to implement on my pages!
I did run into one problem with LightBox though. Your menu doesn’t seem to want to run on the pages that use lightbox.
I’m using your Simple JQuery Accordion menu – Redux 2 along with the jquery cookie plugin and the most recent versions of both LightBox2 and jquery.js.
Have you run into this before? Is there an easy fix to get all this js to coexist on one page?
Thank you,
Stewart
At 24 February '10 - 07:07 naro wrote:
At 25 February '10 - 02:06 Manolis wrote:
Thanks
At 26 February '10 - 05:14 lukas wrote: