<

The simplest jQuery Accordion ever

Published on
7,503 Points
2,403 Views
11 Endorsements
Last Modified:
Marco Gasi
Freelance, I like to share what I know. Find out my articles in my learner-to-learners blog codingfix.com
How to build a simple, quick and effective accordion menu using just 15 lines of jQuery and 2 css classes

Sometime ago someone asked in this Experts-Exchange question how to build an Accordion menu . Well, Accordion menus are really fascinating: they take up little space in our page even if they hold tenths of menu items and this way Accordion menus allow us to build very large menus without breaking our layout. And that animation! Don't you find it amazing?

For those who ignore what an accordion menu is, let me use Wikipedia words:

 


The graphical control element accordion is a vertically stacked list of items, such as labels or thumbnails. Each item can be "expanded" or "stretched" to reveal the content associated with that item. There can be zero expanded items, exactly one, or more than one items expanded at a time, depending on the configuration.
The term stems from the musical accordion in which sections of the bellows can be expanded by pulling outward.

Maybe some images can clarify the concept:

 

accordion.jpg

As you can see, in the first image the menu is closed; when you click, let's say, 'First courses' item, its submenu is shown. But when you click another item, 'Steak' for instance, this one is shown whereas the first one is gracefully hidden.

To witness the success of this technique is simply the extraordinary number of plugins that you can find on the net: just go to Google and type 'Accordion plugin' and you'll navigate in an ocean of different options.


But I want to show you is that you don't need any plugin to build a fully functional, infinitely extensible Accordion menu: just 11 lines of jQuery (parenthesis included)!


The simplest accordion menu ever!


Let's start with our Accordion. It will have a couple of great features:

  1. it can be extended as we need without modifying the underlying jQuery code: we can add an infinite number of submenus and items just using a couple of css classes;
  2. every time we'll click on a menu item to show its children we want automatically close any other open menu regardless its level (except of course the one we are in).


The basic markup


So, look at the following markup for our menu. We'll use the element nav to wrap the series of unordered lists that will build menus and submenus. We give to the main list the id "mg-accordion" (you know, mg stays for Marco Gasi ;) ) Then we'll use class "dropdown" to mark all li elements which hold a submenu and the class "submenu" to mark the ul element which represent the submenu hold by the dropdown list item. In the following snippet you can see highlighted all the lines where these classes are used:

<nav>
    <ul id="mg-accordion" role="navigation" class="row">
        <li><a href="#" title="">All Italian Recipes</a></li>
        <li class="dropdown"><a href="#" title="">First courses</a>  
            <ul class="submenu">
                <li><a href="#">All first courses</a></li>    
                <li><a href="#">All pasta's recipes</a></li>    
                <li><a href="#">All rice's recipes</a></li>    
                <li class="dropdown"><a href="#"> Pasta</a>                 
                    <ul class="submenu">
                        <li><a href="#">Carbonara</a></li>    
                        <li><a href="#">Amatriciana</a></li>    
                        <li><a href="#">Al pesto</a></li>    
                        <li><a href="#">Pomodoro e basilico</a></li>    
                    </ul>
                </li>
                <li class="dropdown"><a href="#">Rice</a>                 
                    <ul class="submenu">
                        <li><a href="#">Milanese</a></li>
                        <li><a href="#">With mushrooms</a></li>
                        <li><a href="#">With peas</a></li>
                        <li><a href="#">With sea food</a></li>
                    </ul>
                </li>
            </ul>
        </li>
        <li class="dropdown"><a href="#">Steack</a>  
            <ul class="submenu">
                <li><a href="#">Stroganoff steaks</a></li>    
                <li><a href="#">Steak & chips</a></li>    
                <li><a href="#">Steak in red wine sauce</a></li>    
                <li><a href="#"> Horseradish butter steaks</a></li>
            </ul>
        </li>
        <li class="dropdown"><a href="#">Fishes</a>  
            <ul class="submenu">
                <li><a href="#">Smoky hake, beans & greens</a></li>    
                <li><a href="#">Grilled miso salmon with rice noodles</a></li>    
                <li><a href="#">Coconut fish curry</a></li>    
                <li><a href="#">Seafood tagine</a></li>    
            </ul>
        </li>
        <li class="dropdown"><a href="#">Fruits</a>  
            <ul class="submenu">
                <li><a href="#">Apricots in syrup with rosemary</a></li>    
                <li><a href="#">Black cherries cinnamon</a></li>    
                <li><a href="#">Caramelized pineapple with cream</a></li>    
            </ul>
        </li>
        <li class="dropdown"><a href="#">Desserts</a>  
            <ul class="submenu">
                <li><a href="#">Chocolate pudding</a></li>    
                <li><a href="#">Tuscan chestnut cake</a></li>    
                <li><a href="#">Hazelnut tart with fig jam</a></li>    
            </ul>
        </li>
    </ul>
</nav>    

Keep in mind you can add as many submenus as you need without change a single comma of the jquery code.


Go with jQuery


What we want to do is to convert this simple list in a fully working Accordion menu.

We want three things:


  1. clicking on an item will open its submenu and clicking that item again will hide the submenu
  2. clicking on an item will hide any visible submenu before to show the submenu child of the clicked item
  3. this mechanism must work respect any level of nested submenus (in the sample above we have three)


Let's go to jQuery. First, we need to embed jQuery:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Is document ready?

$(document).ready(function (){

Now we have to attach an event handler to all anchor elements for the list items which have a submenu. We do this in two steps just to make it a bit more clear:

// first we get our accordion menu and we put it in the variable mymenu
var mymenu = $('ul#mg-accordion');
// then we create the variable dropdowns which holds all anchors children of list items of class 
// dropdowns. These anchors are the ones we have to attach the event handler to: clicking on them will how 
// the hidden submenu
var dropdowns = $(mymenu.find('li.dropdown > a'));

And now the accordion code:

dropdowns.on('click', function (e) {
    //prevent default behavior
    e.preventDefault();
    // we are clicking on an anchor within a list item
    // so we find all ul.submenu elements which are
    // children of any list item which stays at the
    // same level of its parent
    var items = $(this).parents().siblings().find('ul.submenu');
    // for each found ul element we do the following
    items.each(function () {
        if ($(this).is(':visible')) {
            $(this).slideUp('slow');
        }
    });
    // show and hide lists
    $(this).siblings('ul.submenu').slideToggle();
});

If you want allow more than one submenu be visible at the same time you can just delete a few lines of code:

var mymenu = $('ul#mg-accordion');
var dropdowns = $(mymenu.find('li.dropdown > a'));
dropdowns.on('click', function (e) {
    e.preventDefault();                             
    $(this).siblings('ul.submenu').slideToggle();
});


Putting it all together!


That's all. You can style it as you prefer and you have no limit but your fantasy! :-)

Putting it all together we get the following code: this is exactly the same code you can see running above in my small accordion menu example.

As you can see, I have added some code to put a + (plus) and - (minus) signs near to open and closed submenu and to change them accordingly to the user choices. See the comments in the code to learn more about this.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Accordion test</title>
    <style>
      ul{
        list-style-type: none;                          
      }
      li.dropdown > ul{
        display: none;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="row">
        <div class="col-12">
          <nav class="my-menu">
            <ul id="mg-accordion"class="row"> 
              <li><a href="#" title="">All Italian Recipes</a></li>
              <li class="dropdown"><a href="#" title="">First courses</a>  
                <ul class="submenu">
                  <li><a href="#">All first courses</a></li>    
                  <li><a href="#">All pasta's recipes</a></li>    
                  <li><a href="#">All rice's recipes</a></li>    
                  <li class="dropdown"><a href="#"> Pasta</a>                 
                    <ul class="submenu">
                      <li><a href="#">Carbonara</a></li>    
                      <li><a href="#">Amatriciana</a></li>    
                      <li><a href="#">Al pesto</a></li>    
                      <li><a href="#">Pomodoro e basilico</a></li>    
                    </ul>
                  </li>
                  <li class="dropdown"><a href="#">Rice</a>                 
                    <ul class="submenu">
                      <li><a href="#">Milanese</a></li>
                      <li><a href="#">With mushrooms</a></li>
                      <li><a href="#">With peas</a></li>
                      <li><a href="#">With sea food</a></li>
                    </ul>
                  </li>
                </ul>
              </li>
              <li class="dropdown"><a href="#">Steack</a>  
                <ul class="submenu">
                  <li><a href="#">Stroganoff steaks</a></li>    
                  <li><a href="#">Steak & chips</a></li>    
                  <li><a href="#">Steak in red wine sauce</a></li>    
                  <li><a href="#"> Horseradish butter steaks</a></li>
                </ul>
              </li>
              <li class="dropdown"><a href="#">Fishes</a>  
                <ul class="submenu">
                  <li><a href="#">Smoky hake, beans & greens</a></li>    
                  <li><a href="#">Grilled miso salmon with rice noodles</a></li>    
                  <li><a href="#">Coconut fish curry</a></li>    
                  <li><a href="#">Seafood tagine</a></li>    
                </ul>
              </li>
              <li class="dropdown"><a href="#">Fruits</a>  
                <ul class="submenu">
                  <li><a href="accordion.php">Apricots in syrup with rosemary</a></li>    
                  <li><a href="#">Black cherries cinnamon</a></li>    
                  <li><a href="#">Caramelized pineapple with cream</a></li>    
                </ul>
              </li>
              <li class="dropdown"><a href="#">Desserts</a>  
                <ul class="submenu">
                  <li><a href="#">Chocolate pudding</a></li>    
                  <li><a href="#">Tuscan chestnut cake</a></li>    
                  <li><a href="#">Hazelnut tart with fig jam</a></li>    
                  <li class="dropdown"><a href="#">Desserts</a>  
                    <ul class="submenu">
                      <li><a href="#">Chocolate pudding</a></li>    
                      <li><a href="#">Tuscan chestnut cake</a></li>    
                      <li><a href="#">Hazelnut tart with fig jam</a></li>    
                      <li class="dropdown"><a href="#">Desserts</a>  
                        <ul class="submenu">
                          <li><a href="#">Chocolate pudding</a></li>    
                          <li><a href="#">Tuscan chestnut cake</a></li>    
                          <li><a href="#">Hazelnut tart with fig jam</a></li>    
                          <li class="dropdown"><a href="#">Desserts</a>  
                            <ul class="submenu">
                              <li><a href="#">Chocolate pudding</a></li>    
                              <li><a href="#">Tuscan chestnut cake</a></li>    
                              <li><a href="#">Hazelnut tart with fig jam</a></li>    
                            </ul>
                          </li>
                          <li class="dropdown"><a href="#">Desserts</a>  
                            <ul class="submenu">
                              <li><a href="#">Chocolate pudding</a></li>    
                              <li><a href="#">Tuscan chestnut cake</a></li>    
                              <li><a href="#">Hazelnut tart with fig jam</a></li>    
                            </ul>
                          </li>
                        </ul>
                      </li>
                      <li class="dropdown"><a href="#">Desserts</a>  
                        <ul class="submenu">
                          <li><a href="#">Chocolate pudding</a></li>    
                          <li><a href="#">Tuscan chestnut cake</a></li>    
                          <li><a href="#">Hazelnut tart with fig jam</a></li>    
                          <li class="dropdown"><a href="#">Desserts</a>  
                            <ul class="submenu">
                              <li><a href="#">Chocolate pudding</a></li>    
                              <li><a href="#">Tuscan chestnut cake</a></li>    
                              <li><a href="#">Hazelnut tart with fig jam</a></li>    
                            </ul>
                          </li>
                          <li class="dropdown"><a href="#">Desserts</a>  
                            <ul class="submenu">
                              <li><a href="#">Chocolate pudding</a></li>    
                              <li><a href="#">Tuscan chestnut cake</a></li>    
                              <li><a href="#">Hazelnut tart with fig jam</a></li>    
                            </ul>
                          </li>
                        </ul>
                      </li>
                    </ul>
                  </li>
                </ul>
              </li>
            </ul> 
          </nav>        
        </div>
      </div>
    </div>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script type="text/javascript">
       $(document).ready(function () {
           var mymenu = $('ul#mg-accordion');
           var dropdowns = $(mymenu.find('li.dropdown > a'));
           dropdowns.each(function () {
               $(this).prepend('+ ');//we add a + (plus) symbol to highlight the fact that the node holds a submenu
           });
           dropdowns.on('click', function (e) {
               e.preventDefault();
               //Following 5 lines change the plus/minus symbols accordingly to the submenu state
               if ($(this).text().charAt(0) === '+') {
                   $(this).text($(this).text().replace('+', '-'));
               } else {
                   $(this).text($(this).text().replace('-', '+'));
               }
               var items = $(this).parents().siblings().find('ul.submenu');
               items.each(function () {
                   if ($(this).is(':visible')) {
                       $(this).slideUp('slow');
                       //we update plus/minus symbol in all siblings submenus 
                       $(this).siblings('.dropdown a').text($(this).siblings('.dropdown a').text().replace('-', '+'));
                   }
               });
               $(this).siblings('ul.submenu').slideToggle();
           });
       });
    </script>           
  </body>
</html>

That's all, people. Hope this help :)

11
Comment
Author:Marco Gasi
6 Comments
 
LVL 66

Expert Comment

by:Jim Horn
Nicely illustrated.  Voted Yes.
0
 
LVL 31

Author Comment

by:Marco Gasi
Thank you for the upvote and for having set my comment as private, Jim.
On to the next :-)
0
 

Expert Comment

by:Kibbage
Great article, thank you.
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 36

Expert Comment

by:Loganathan Natarajan
Good Article
0
 
LVL 11

Expert Comment

by:Ackles
Awesome!!!
Simple Beautiful
0
 

Expert Comment

by:Eduardo Fuerte
Mario

Very good example and good foods!!!

Thanks
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Join & Write a Comment

Viewers will get an overview of the benefits and risks of using Bitcoin to accept payments. What Bitcoin is: Legality: Risks: Benefits: Which businesses are best suited?: Other things you should know: How to get started:
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)
Suggested Courses
Course of the Month13 days, 14 hours left to enroll

Keep in touch with Experts Exchange

Tech news and trends delivered to your inbox every month