Building Accessible Menu Systems

About The Author

Heydon Pickering (@heydonworks) has worked with The Paciello Group, The BBC, Smashing Magazine, and Bulb Energy as a designer, engineer, writer, editor, and … More about Heydon ↬

Email Newsletter

Weekly tips on front-end & UX.
Trusted by 200,000+ folks.

Creating inclusive experiences is a question of using the right menu patterns in the right places, with the right markup and behavior. In design, we often make the mistake of giving different things the same name. They appear similar, but appearances can be deceptive. In terms of inclusion, it may lead you to repurpose a semantically and behaviorally inappropriate component. Users will expect one thing and get another. In this article, Heydon Pickering will give you an insight into inclusive menus and menu buttons.

Editor’s Note: This article originally appeared on Inclusive Components. If you’d like to know more about similar inclusive component articles, subscribe to the RSS feed. By supporting inclusive-components.design on Patreon, you can help to make it the most comprehensive database of robust interface components available.

There are lots of different types of menu on the web. Creating inclusive experiences is a question of using the right menu patterns in the right places, with the right markup and behavior.

Classification is hard. Take crabs, for example. Hermit crabs, porcelain crabs, and horseshoe crabs are not — taxonomically speaking — true crabs. But that doesn’t stop us using the “crab” suffix. It gets more confusing when, over time and thanks to a process called carcinisation, untrue crabs evolve to resemble true crabs more closely. This is the case with king crabs, which are believed to have been hermit crabs in the past. Imagine the size of their shells!

In design, we often make the same mistake of giving different things the same name. They appear similar, but appearances can be deceptive. This can have an unfortunate effect on the clarity of your component library. In terms of inclusion, it may also lead you to repurpose a semantically and behaviorally inappropriate component. Users will expect one thing and get another.

The term “dropdown” names a classic example. Lots of things “drop down” in interfaces, including the set of options from a select element, and the JavaScript-revealed list of links that constitute a navigation submenu. Same name; quite different things. (Some people call these “pulldowns”, of course, but let’s not get into that.)

Dropdowns which constitute a set of options are often called “menus”, and I want to talk about these here. We shall be devising a true menu, but there’s plenty to be said about not-really-true menus along the way.

Let’s start with a quiz. Is the box of links hanging down from the navigation bar in the illustration a menu?

A navigation bar with includes a shop link, underneath which hangs a set of three further links to dog costumes, waffle irons, and magical orbs respectively.
A navigation bar with includes a shop link, underneath which hangs a set of three further links to dog costumes, waffle irons, and magical orbs respectively. (Large preview)

The answer is no, not a true menu.

It’s a longstanding convention that navigation schemas are composed of lists of links. A convention nearly as longstanding dictates that sub-navigation should be provided as nested lists of links. If I were to remove the CSS for the component illustrated above, I should see something like the following, except colored blue and in Times New Roman.

Semantically speaking, nested lists of links are correct in this context. Navigation systems are really tables of content and this is how tables of content are structured. The only thing that really makes us think “menu” is the styling of the nested lists and the way they are revealed on hover or focus.

That’s where some go wrong and start adding WAI-ARIA semantics: aria-haspopup="true", role="menu", role="menuitem" etc. There is a place for these, as we’ll cover, but not here. Here are two reasons why:

  1. ARIA menus are not designated for navigation but for application behavior. Imagine the menu system for a desktop application.
  2. The top-level link should be usable as a link, meaning it does not behave like a menu button.

Regarding (2): When traversing a navigation region with submenus, one would expect each submenu to appear upon hovering or focusing the "top level" link ("Shop" in the illustration). This both reveals the submenu and places its own links in focus order. With a little help from JavaScript capturing focus and blur events to persist the appearance of the submenus while needed, someone using the keyboard should be able to tab through each link of each tier, in turn.

Menu buttons which take the aria-haspopup="true" property do not behave like this. They are activated on click and have no other purpose than to reveal a secreted menu.

ebook discounts bieten wir
Left: a menu button labeled 'menu' with a down-pointing arrow icon and the aria-expanded = false state. Right: The same menu button but with the menu open. This button is in the aria-expanded = true state. (Large preview)

As pictured, whether that menu is open or closed should be communicated with aria-expanded. You should only change this state on click, not on focus. Users do not usually expect an explicit change of state on a mere focus event. In our navigation system, state doesn’t really change; it’s just a styling trick. Behaviorally, we can Tab through the navigation as if no such show/hide trickery were occurring.

The Problem With Navigation Submenus

Navigation submenus (or "dropdowns" to some) work well with a mouse or by keyboard, but they’re not so hot when it comes to touch. When you press the top-level "Shop" link in our example for the first time, you are telling it to both open the submenu and follow the link.

There are two possible resolutions here:

  1. Prevent the default behavior of top-level links (e.preventDefault()) and script in full WAI-ARIA menu semantics and behavior.
  2. Make sure each top-level destination page has a table of contents as an alternative to the submenu.

(1) is unsatisfactory because, as I noted previously, these kinds of semantics and behaviors are not expected in this context, where links are the subject controls. Plus users could no longer navigate to a top-level page, if it exists.

Sidenote: Which Devices Are Touch Devices?

It’s tempting to think, “this isn’t a great solution, but I’ll only add it for touch interfaces”. The problem is: how does one detect if a device has a touch screen?

You certainly shouldn’t equate "small screen" with "touch activated". Having worked in the same office as folks making touch displays for museums, I can assure you that some of the largest screens around are touch screens. Dual keyboard and touch input laptops are becoming increasingly prolific too.

By the same token, many but not all smaller devices are touch devices. In inclusive design, you cannot afford to make assumptions.

Resolution (2) is more inclusive and robust in that it provides a "fallback" for users of all inputs. But the scare quotes around the fallback term here are quite deliberate because I actually think in-page tables of content are a superior way of providing navigation.

The award winning Government Digital Services team would appear to agree. You may also have seen them on Wikipedia.

Gov.uk tables of content are minimal with hyphens as list styles. Wikipedia provides a bordered grey box with numbered items. Both are labeled contents.
Gov.uk tables of content are minimal with hyphens as list styles. Wikipedia provides a bordered grey box with numbered items. Both are labeled contents.

Tables Of Content

Tables of content are navigation for related pages or page sections and should be semantically similar to main site navigation regions, using a `