Multi-Level Accordion Menu

Multi-Level Accordion Menu

A simple CSS accordion menu with support for sub level items.

Nucleo icons

Sponsored by Nucleo, a free application to collect, customize and export all your icons as icon font and SVG symbols. Made by the CodyHouse folks!

Do you want to include this resource in a product offered for sale? Learn more about our Extended License

Today's resource is a handy accordion menu with support for groups/subitems. It works with CSS only, using the :checked pseudo-class selector on the checkboxes input elements. However we included a version with jQuery as well, in case you prefer a subtle animation compared to the instant default effect. Your call!

The first user case I can think of for this resources is a "layer organizer". Think of Sublime Text sidebar, or Photoshop layer window. Anyway, I'm sure you'll find a use for this new snippet to store in your arsenal ;)

Icons: Nucleoapp.com

Creating the structure

The HTML structure is pretty simple: the accordion is an unordered list. If a list item contains subitems, then we insert an input[type=checkbox] and its label. Also, we add the .has-children class to the list item. All "standard" list items contain just an anchor tag.

<ul class="cd-accordion-menu">
   <li class="has-children">
      <input type="checkbox" name ="group-1" id="group-1" checked>
      <label for="group-1">Group 1</label>

      <ul>
         <li class="has-children">
            <input type="checkbox" name ="sub-group-1" id="sub-group-1">
            <label for="sub-group-1">Sub Group 1</label>

            <ul>
               <li><a href="#0">Image</a></li>
               <li><a href="#0">Image</a></li>
               <li><a href="#0">Image</a></li>
            </ul>
         </li>
         <li><a href="#0">Image</a></li>
         <li><a href="#0">Image</a></li>
      </ul>
   </li>

   <li><a href="#0">Image</a></li>
   <li><a href="#0">Image</a></li>
</ul> <!-- cd-accordion-menu -->

Adding style

We use a smart (and quite standard nowadays) technique to detect the click and show sub content with CSS only: by including a checkbox input element, we can use the :checked pseudo-class and the adjacent sibling selector (div + div) to change the display mode of the sub <ul> element from "none" to "block".

Step by step: first of all, we have to make sure that the checkbox input element covers the entire list item that contains subitems. Put in other words: we need to create a custom checkbox. So, firstly, you need to make sure that when you click on the label, the checkbox is checked/unchecked as well. This is achieved by using the "for" attribute inside the label (label "for" attribute = input "name" and "id" attributes. See html section above). This way you can simply hide the input element and work with the label instead.

.cd-accordion-menu input[type=checkbox] {
  /* hide native checkbox */
  position: absolute;
  opacity: 0;
}
  .cd-accordion-menu label, .cd-accordion-menu a {
  position: relative;
  display: block;
  padding: 18px 18px 18px 64px;
  background: #4d5158;
  box-shadow: inset 0 -1px #555960;
  color: #ffffff;
  font-size: 1.6rem;
}

Now notice in the HTML structure that input, label and the unordered list (that we make visible on click) are siblings. By using the :checked pseudo-class, you can set the following process in motion: when the checkbox input is checked (click on label), then take the <ul> sibling element and change its display value from "none" to "block":

.cd-accordion-menu ul {
  /* by default hide all sub menus */
  display: none;
}

.cd-accordion-menu input[type=checkbox]:checked + label + ul,
.cd-accordion-menu input[type=checkbox]:checked + label:nth-of-type(n) + ul {
  /* use label:nth-of-type(n) to fix a bug on safari (<= 8.0.8) with multiple adjacent-sibling selectors*/
  /* show children when item is checked */
  display: block;
}

If you want to gently animate the opening phase, then include the .js file as well. Also remember to add the .animate class to the main .cd-accordion-menu element (this will animate the arrow rotation).

Join our newsletter

Get our monthly recap with the latest CodyHouse news