The simplest jQuery Accordion ever

Marco GasiFreelancer
CERTIFIED EXPERT
Freelance, I like to share what I know. Find out my articles in my learner-to-learners blog https://codingfix.com
Published:
Updated:
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
3,718 Views
Marco GasiFreelancer
CERTIFIED EXPERT
Freelance, I like to share what I know. Find out my articles in my learner-to-learners blog https://codingfix.com

Comments (6)

Marco GasiFreelancer
CERTIFIED EXPERT
Top Expert 2010

Author

Commented:
Thank you for the upvote and for having set my comment as private, Jim.
On to the next :-)
Ken GladdenPartner

Commented:
Great article, thank you.
Loganathan NatarajanLAMP Developer
CERTIFIED EXPERT

Commented:
Good Article

Commented:
Awesome!!!
Simple Beautiful
Eduardo FuerteDeveloper and Analyst

Commented:
Mario

Very good example and good foods!!!

Thanks

View More

Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.