Open Sub Menu

elmenu

A lightweight, responsive jQuery menu system

Current Version 1.1.0
See the repo for changelog info.

Vanilla JavaScript version coming soon

elmenu is kind of a silly name. It's not meant to be a Spanish for "The Menu." I made it (elmnt), and it's a menu system. There you go. Clever, I know.

Features:

  • The slide-in mobile menu auto-populates with the header navigation content.
  • The minified elmenu script is just 2kB
  • The compiled/minified elmenu Sass partial is 4kB
  • The mobile nav links that contain a sub-nav (clones of the header nav links with drop-downs) have both a parent anchor link, and a separate toggle trigger for the sub-links.
  • The elmenu Sass partial is highly portable. The additional styles in this demo have no effect on the menu system. As long as you use the markup structure & associated BEM classes, you should be able to drop it into your project without too much clean-up.

 

Requirements:

This script requires the jQuery library, and assumes you're using a Sass framework of some kind for your styles.

Usage:

1) Basic template structure:

elmenu uses an off-canvas menu system for mobile display. Your top-level markup should look like this:


    

Page Content

2) Header Navigation:

As you can see in the top-level markup structure, above, there are two main elements where everything happens: #elmain (the desktop nav) and #elmobile (the mobile nav). You're going to put all your navigation in the #elmain nav, and you're not going to touch the #elmobile nav. That gets populated by the elmenu script.

The key ingredient is following a very specific structure in your markup (and attached BEM classes). In this demo page, I've got two header nav bars (a 'utility' nav, followed by a 'main' nav). This is a pretty common convention. You could have a similar setup. You could have only one nav bar. You could have three, or four. That might be an awful UX, but the point being: it's possible.

I'm using some wrappers, inside the #elmain, with the .navholder-- prefix. These just allow me some basic styling on each menu container.

Drill down a bit more, and you'll see the .nav-- classes. This is the class we're targeting to pick up the stuff we'll clone into the mobile menu. I could have targeted each 'nav' tag, but there's an outside chance you might want to target something in the header that's not a semantic 'nav' element. So I left those alone.

To better demonstrate this hierarchy, here are some possible examples. You don't need to follow my 'utility,' main,' and 'social,' idea. I just did that because it's pretty common. Let's assume you have two nav bars, as in this demo page: 'utility' and 'main.'


    

    
    

And the 'utility' has a couple sub-elements. This is very flexible. Just keep the .navholder-- wrapper and .nav-- child setup, and you can have as many individual pieces inside one .navholder-- as is logical for you.

Or perhaps you just have one nav bar, consisting of your site's navigation, and a search bar:


    
    

The important takeaways:

  1. Any module you want placed in the mobile menu must have the .nav-- class.
  2. The .nav--main element is where you want to put your multi-level menu, if you're using one. We'll get into that structure next.

 

3) Header Navigation: Complete BEM style class structure, with all the options

Now we'll attach a complete set of BEM classes to complete the visual styles for the entire header menu. When the individual pieces of your header nav are cloned into your mobile menu, these classes are duplicated with a special prefix to handle all the unique mobile styling.

Notice the general BEM (element) suffix convention I'm using for the lists:

__list (the ul)
__item (the li)
__link (the a)

Here's the whole working elmenu header, as in this demo, with some detailed explanation to follow:


    
Open Sub Menu

NOTE: I chose to modify the class names via jQuery because it's a fairly simple process, and, more important, it gets us away from the need to use the same class names in the mobile menu, re-styled with the specificity of the parent ID. While this is effective, it's generally seen as poor practice to use an ID for such a high-level of specificity, over-riding classes several levels into the markup.

In other words, this:

    
    .child {}
    .grandchild {
        color: blue;
    }
    .m-child {}
    .m-grandchild {
        color: red;
    }
    
    

...is better than this:

    
    #desktop .child .grandchild {
        color: blue;
    }
    #mobile .child .grandchild {
        color: red;
    }
    
    
4) Setting it up:

You can start by copying the entire block, above, and dropping in your links. Of course it's likely you're going to need to customize it. Refer to the previous couple code blocks again, as a reminder how you can easily customize it. Just remember to keep your BEM classes (and of course your IDs) in place.

Script: Drop the pre-compiled elmenu.js script into your local build.

Styles: Drop the pre-compiled _elmenu.scss partial into your local build.

I've tried, as much as possible, to keep the Sass partial completely portable. The IDs and classes are uniquely specific, so you shouldn't run into any conflicts. All the variables are at the top of the partial. Move them into your own variables partial, or leave them in place.