Hey, stop messing around. It's responsive, I promise.

How to:

Submenus

This is what we will be creating:

  • Inbox
    • Unread
    • Read
    • Sent
    • Flagged
  • Documents
    • Word-documents
    • Powerpoint-documents
    • Excel-documents
  • Statistics
    • Area Chart
    • Line Chart
    • Pie Chart

This can be used for many things, such as: a way to make hamburgermenus more compact, handling a folder structure or as an accordion for showing and hiding content. The structure is pretty straight forward, we will create an unordered list that will contain all the menu-items and then separate the upper-menus from the lower-menus by assigning corresponding classes to them. Like this:

Copied!
<ul> <li class="upper"></li> <li class="lower"></li> <li class="upper"></li> <li class="lower"></li> <li class="upper"></li> <li class="lower"></li> </ul>

It is important that you place them like above, in an every other fashion, otherwise you will encounter problems later on with the JavaScript handling the collapsing of your menus. Now we will need to add some content, for the upper-menus we can simply enter the text we want in the <li>. But for the lower-menus we will need to add another unordered list inside the "lower" list-item and fill it with the menu-items we want to go in there before we can add the content for them.

Copied!
<ul> <li class="upper">Upper Item</li> <li class="lower"> <ul> <li>Lower Item</li> <li>Lower Item</li> <li>Lower Item</li> </ul> </li> <li class="upper">Upper Item</li> <li class="lower"> <!-- Same as above --> </li> <li class="upper">Upper Item</li> <li class="lower"> <!-- Same as above --> </li> </ul>

Let's add some CSS to style it up!

Copied!
ul { margin: 0; padding: 0; } li { padding: 0.8em 1em; } li.upper { background: #3498db; cursor: pointer; } li.upper.collapsed { background: #258cd1; } li.lower { background: #3f9ddd; max-height: 0; overflow: hidden; padding: 0 0.3em; -webkit-transition: max-height 0.3s ease; /* Chrome */ -moz-transition: max-height 0.3s ease; /* Firefox */ transition: max-height 0.3s ease; } li.lower ul > li { font-size: 0.8em; cursor: pointer; } li.lower ul > li:nth-last-child(1) { padding-bottom: 1em; }

The max-height: 0 and overflow: hidden on the li.lower selector are the most important bits of code in there, as they − together with some nifty JavaScript below − control if the submenus are supposed to appear or not. Let's add that nifty JavaScript! To make this easier I am using jQuery to handle the click-function and for toggling the .collapsed class. Don't worry if you haven't used jQuery before, I will walk you through the code below the snippet.

Copied!
$(".upper").click(function(){ $(this).toggleClass("collapsed"); var collapsedMenu = this.nextElementSibling; if (collapsedMenu.style.maxHeight) { collapsedMenu.style.maxHeight = null; } else { collapsedMenu.style.maxHeight = collapsedMenu.scrollHeight + "px"; } });

The $ symbol followed by parentheses is a mashup of the more common getElementBy... method from vanilla JavaScript and can select both classes, ids and tags making it very easy to select your HTML elements. By assigning the .click function it will run the code within when you click the element that you selected with $(). I begin by using the local variable this to apply the class .collapsed to the specific upper-menu-item that I click on. The if statement checks if the lower-menu is shown by checking its max-height property. If shown, set max-height to null, else set it to its scrollHeight (i.e. 100%). This is what we have accomplished so far:

  • Upper Item
    • Lower Item
    • Lower Item
    • Lower Item
  • Upper Item
    • Lower Item
    • Lower Item
    • Lower Item
  • Upper Item
    • Lower Item
    • Lower Item
    • Lower Item

Now that we have the overall look and functionality of the submenus, let's add some icons and animations to make it even prettier! We'll begin by adding some icons to give the user some feedback if the submenu is collapsed or not. I will be using font icons from Font Awesome because they are − as stated in the name − awesome. Go to their website for instructions on how to set it up. To add these icons we will use the ::after selector on the .upper list-item and assign the unicode for the icon in the content, as such:

Copied!
li.upper::after { content: "\f078"; font-family: FontAwesome; float: right; /* Let's add a transition to animate the icon when clicked */ -webkit-transition: transform 0.2s ease; /* Chrome */ -moz-transition: transform 0.2s ease; /* Firefox */ transition: transform 0.2s ease; } /* And now the transform for the ::after when .upper has the class collapsed */ li.upper.collapsed::after { -webkit-transform: rotate(180deg); /* Chrome */ -moz-transform: rotate(180deg); /* Firefox */ transform: rotate(180deg); }

And we're pretty much done now, you can go ahead and style the submenus to your liking, change to more fitting linknames and icons, and maybe even add some sweet hover effects? The choice is yours. If you have questions or feedback on this little tutorial please do email me at

Download code

HTML

Copied!
<ul> <li class="upper">Upper Item</li> <li class="lower"> <ul> <li>Lower Item</li> <li>Lower Item</li> <li>Lower Item</li> </ul> </li> <li class="upper">Upper Item</li> <li class="lower"> <ul> <li>Lower Item</li> <li>Lower Item</li> <li>Lower Item</li> </ul> </li> <li class="upper">Upper Item</li> <li class="lower"> <ul> <li>Lower Item</li> <li>Lower Item</li> <li>Lower Item</li> </ul> </li> </ul>

CSS

Copied!
ul { margin: 0; padding: 0; } li { padding: 0.8em 1em; } li.upper { background: #3498db; cursor: pointer; } li.upper::after { content: "\f078"; font-family: FontAwesome; float: right; -webkit-transition: transform 0.2s ease; /* Chrome */ -moz-transition: transform 0.2s ease; /* Firefox */ transition: transform 0.2s ease; } li.upper.collapsed { background: #258cd1; } li.upper.collapsed::after { -webkit-transform: rotate(180deg); /* Chrome */ -moz-transform: rotate(180deg); /* Firefox */ transform: rotate(180deg); } li.lower { background: #3f9ddd; max-height: 0; overflow: hidden; padding: 0 0.3em; -webkit-transition: max-height 0.3s ease; /* Chrome */ -moz-transition: max-height 0.3s ease; /* Firefox */ transition: max-height 0.3s ease; } li.lower ul > li { font-size: 0.8em; cursor: pointer; } li.lower ul > li:nth-last-child(1) { padding-bottom: 1em; }

JavaScript

Copied!
$(".upper").click(function(){ $(this).toggleClass("collapsed"); var collapsedMenu = this.nextElementSibling; if (collapsedMenu.style.maxHeight) { collapsedMenu.style.maxHeight = null; } else { collapsedMenu.style.maxHeight = collapsedMenu.scrollHeight + "px"; } });