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
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
<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 --> |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
.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”:
1 2 3 4 5 6 7 8 9 10 11 |
.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).