How do you build a mobile-first, progressively enhanced, responsive navigation menu? Let me introduce you to Menu Object (mo.js), a system for handling menus from the ground up. At its most basic level, mo.js dynamically adds and removes classes from menu elements to allow various menu states to be styled using CSS. For those of you dying to get right to the code, you can check out the Menu Object repository on Github. For everyone else, let’s start at the beginning…
Granted, this is not the ideal menu in every situation, but it works acceptably in most circumstances. The biggest drawback is the lack of :hover support on certain devices, but we will address that later.
On desktops or laptops with reasonable screen sizes, we can assume that our menu won’t be wrapping to a second line. This allows us to use CSS media queries to align our top level menu to the left. This is not required, but is often the desired menu style for non-mobile devices.
As you can see in the image above, the menu item alignment shifts to the left on larger devices.
While it is possible to change the menu layout on mobile devices using only CSS media queries, I don’t recommend it for the following reason. Imagine a mobile menu like the one pictured below, but with 20 menu items.
Now imagine such a menu at the top of every page! On sites with such large menus, scrolling down past the menu on every new page load quickly becomes tedious.
In our case, mo.js automatically adds a new HTML class to the menu if the viewport is smaller than a particular breakpoint. It also adds the menu toggle button in place of the menu.
As you can see in the image above, the phone has a vertical menu with the toggle button, the tablet has a horizontal list of centered links, and the desktop/laptop combo have the left aligned list of links.
Although the screen shots up to this point show no sign of the existence of any sub-menus, this particular example actually contains multiple layers of sub-menus. As (responsible) designers and developers, we should not expect our site visitors to blindly stumble upon our sub-menus, or force them to use trial and error to figure out which (if any) menu items contain sub-menus. Thankfully, mo.js automatically adds an HTML class to any menu item containing a sub-menu. This class can then be used to add a sub-menu indicator (such as an arrow) to items containing a sub-menu.
…and that is one way to build a mobile-first, progressively enhanced, responsive navigation menu system. How many more buzzwords could possibly be added to that sentence?
Here’s one last screen shot with a few expanded menus.
- mo.js can handle multiple menus on the same page.
- mo.js uses the standard WordPress menu HTML structure. I haven’t tested it with anything else.
- I also wanted to say a special thanks to Brady Vercher of Blazer Six for his feedback and code contributions.