Mobile-friendly toggling menu
Tags: CSS HTML JavaScript
A question I've sometimes puzzled over is how to design a site's main navigation, with say six menu items, so that it looks and behaves in a pleasing way at small device widths. The solution that Responsive Web Design uses is elegant without being too flashy, and uses all three of the web design trio: HTML, CSS and JavaScript. It's only in the last couple of months that I've been delving into JavaScript, so I'm particularly proud of myself for figuring this it out!
Skip to navigationAll menus, great and small
At full mast (desktop screen width), the main navigation appears in the header as a row of links that balance beautifully with the site logo.
At smaller screen widths, the menu seems to disappear, and it's replaced with a black dot in the corner (Figure 2, left). Click or tapping this dot reveals the menu (Figure 2, middle), and a dash of animation to shows the user what's happening (Figure 2, right).
Skip to navigation90% styling, 10% script
What's the secret? It's so simple, it's wonderful! When the toggle is clicked or tapped, a very short script adds or removes a class called is-open
to the <nav>
element. Done. The rest is CSS styling, which controls what the nav element and its children look like with and without the is-open
class. This includes a 0.3-second transition on the nav element's max-height
attribute, which gives us our helpful animation.
Below, I've given my spin on the HTML, CSS and JS required to pull this off.
Skip to navigationHTML markup
The markup for the nav menu is fairly standard:
In my project, I tried using href="#"
for the target of the menu button. The problem was that because the menu button wasn't right at the top of the page as it is in RWD, the screen would lurch jarringly back to the top. I found that href="javascript:void(0)"
prevented this from happening.
CSS styles
The CSS styles are spread across several parts. I've only included the most essential styles here; each project will require its own colours, typography choices, and so on. My key breakpoint is 35em. Below this, the menu is directed by the toggle. Above this, the menu is constantly in view and the toggle button is hidden.
Firstly, this is the styling for the toggle button at a screen width lower than 35em:
Above 35em, the toggle button disappears completely.
At small screen sizes, the nav menu is a single column. Without the is-open
class, the max-height is 0. It is this attribute that opens and closes the menu.
Above 35em, the nav menu appears however you want.
Skip to navigationJavaScript code
In pseudocode, here's what we do:
// When the menu toggle is clicked or tapped,
// toggle the boolean open/closed state
// If state = open,
// add "is-open" to the nav element's list of classes
// If state = closed,
// remove "is-open" from the nav element's list of classes
Here it is in JS:
The spaceIfRequired()
function adds a space if the nav element has other classes attached to it. When minified, this script needs just 263 bytes, so it is definitely worth the extra weight that it adds.
Accessibility
Testing this toggle menu on my devices with all the main browsers, there don't seem to be any problems. Let's try and break it!
Keyboard: I found that I can navigate to the toggle button using the tab key, and in fact, the menu doesn't even need to be open to tab through the menu items. One small problem is that the toggle button doesn't change at all when it has the focus. Perhaps it might be better to change the colour in CSS with #menu-toggle:focus { /* styles */ }
.
Screen reader: Using WebbIE 4, I tried navigating a site I made with this menu structure, and it performs perfectly.
Old browsers: The nav element isn't supported by IE8 or lower, so if it's important to design for this browser, you'd be better off using a div element for the navigation. Apart from that change, the toggle menu should theoretically work.
Skip to navigationMore applications
If we squint just so, we'll almost certainly be able to find other applications for this technique. It would be useful in situations where the user might want to toggle content. For example, imagine a very long, text-heavy document that, for some reason, needs to be contained in a single page. Headings could function as toggle buttons. Clicking or tapping on a heading hides or reveals the content below.
Another potential application I can think of is to include controls that allow the user to change the font, font size, capitalisation, and background colour. These are parameters that can influence the readability of a website, in particular for users with dyslexia and/or visual impairments. Skip to navigation
Conclusion
How nifty is that? So, using a tiny bit of JavaScript to add a class to an object, we can create an elegant, mobile-friendly menu that switches on and off. The beauty of it is that it seems to have no impact on a site's accessibility.
Further reading
This great pen by Geoffrey Crofte demonstrates a very similar technique. The basic functionality is the same. The main difference is that instead of displacing the content below the menu when it opens, the menu is taken out of the flow of the document using relative positioning, and its appearance is controlled with visibility, not max-height.
Update 24/11/2015: Purely by coincidence (I promise), I picked up Ethan Marcotte's Responsive Design: Patterns and Principles not long after I wrote this. In Chapter 2, he covers toggling menus with much more insight than me. In particular, he shows how to ensure that the menu stays visible when the JavaScript fails. Genius!
Skip to navigation
Comments
comments powered by Disqus