A couple weeks ago at the 27th Annual CSUN International Technology and Persons with Disabilities Conference I gave a presentation on accessible dropdown menus. In that presentation, I walked through several examples of accessible menu techniques (and a few not-so-accessible ones). All the examples are available on my Dropdown Menus Test Page.
Dropdown and flyout menus on websites are great for reducing clutter, simplifying page content, and providing a consistent navigation structure that (if done well) makes it easy to find content from anywhere on the site. Unfortunately, very few of the dynamic menus in use today are fully accessible:
- Most dynamic menus depend on users being able to use a mouse. Mousers hover over menu items, which makes dropdown menus appear. If non-mousers tab to those same top-level menu items, they typically can’t make the dropdown menus appear.
Many of these early models are still in use today. Most dynamic menus on the web are structured using standard HTML. A few of these menus position the sub-menus off-screen rather than hiding them with display:none, which means they’re accessible to screen reader users at all times, even though sighted users can’t see them. These menus aren’t perfect—they’re just lists of links, not interactive menus. But technically they’re accessible.
The bigger problem is for sighted non-mousers, who may be navigating the web page with keyboard only, typically using the tab key. When menus are positioned off-screen, they may or may not be re-positioned on-screen when a keyboard user tabs to their parent top-level menu item. Consequently, users can tab through the items in the drop-down menu, but they can’t see them. It’s pretty silly.
Some menus today do actually become visible when they receive keyboard focus, which solves the problem described in the previous paragraph and would seem at first glance to be fully accessible. However, even these menus aren’t very usable because users have to tab and tab and tab and tab, on and on to get through the menus. If there are many items in the menus and submenus, it can take forever to get to the third or fourth top-level menu item.
The Solution Part 1: ARIA
The W3C’s draft specification for Accessible Rich Internet Applications (ARIA) makes it possible to supplement HTML with attributes that explicitly communicate the roles, states, and properties of the various parts that make up a menu system. As assistive technology (AT) users interact with the menu, ARIA passes updated information to their AT, and their AT then communicates that information in meaningful ways.
A dynamic menu system might include the following ARIA markup:
- role=”menubar” on the menubar’s root element, typically a <ul>.
- role=”menu” on the root element for each of the dropdown menus, which typically are either coded as <ul> or <div>.
- role=”menuitem” on each actionable item in the menu system, including those on the menubar and those in drop-down menus and sub-menus
- aria-haspopup=”true” on any item that triggers the display of a dropdown menu. This is typically applied to all top-level menubar items, and to any menu items that have sub-menus.
Putting this all together, an accessible ARIA-enhanced menu would look something like this:
<div role="navigation" aria-label="Main menu"> <ul id="nav" role="menubar"> <li role="menuitem" tabindex="0" aria-haspopup="true"> About <ul role="menu" aria-hidden="true"> <li role="menuitem" tabindex="-1"> <a href="#">News</a> </li> <li role="menuitem" tabindex="-1"> <a href="#">Contact Us</a> </li> </ul> </li> <li role="menuitem" tabindex="0" aria-haspopup="true"> Academics <ul role="menu" aria-hidden="true"> <li role="menuitem" tabindex="-1"> <a href="#">Degree Programs</a> </li> <li role="menuitem" tabindex="-1"> <a href="#">Faculty</a> </li> </ul> </li> </ul> </div>
This is the future of menu system. On my Dropdown Menus Test Page, there are three examples that apply markup similar to this, and the rest of this blog post I’ll be comparing them. They are:
- Simply Accessible CSS Dropdown Menu, an example menu created by Derek Featherstone
- YUI Library MenuNavNode Plugin
- Open Ajax Alliance (OAA) Menubar, with some customizations.
These three example menus differ in other ways too. Please read on!
The Solution Part 2: A Robust Keyboard Model
The WAI-ARIA 1.0 Authoring Practices site includes a standard set of Design Patterns, adopted from the DHTML Style Guide. These design patterns were developed by a group of key stakeholders to define a set of recommended models for how web-based menus and other interactive widgets should behave. In a nutshell, users should be able to tab into the menu, but once the menu has focus, they should be able to navigate left, right, up, and down using the arrow keys. Pressing enter, space, or down arrow on a top-level menu item should trigger the display of the dropdown or flyout menu if one is present, and pressing escape should close it and return focus to the parent menu item. When users tab out of the menu, any open sub-menus should close.
Each of the three example menus implements most of these recommendations. One recommendation that is not currently implemented by YUI, but is implemented by the other two, is support for jumping to a menu item by typing the letter that item starts with. This is a very cool feature, and saves users a lot of keystrokes especially if the menu is large.
Despite the similarities in the example menus, there is one important difference in their keyboard models: How they handle the tab key.
The Tab Key in Dynamic Menus
The DHTML Style Guide says this about the Tab key:
First item in menu bar should be in the tab order (tabindex=0).
The Style Guide does not expressly forbid other items in the menu being in the tab order, and each of the three menus supports tab differently.
In the Simply Accessible menu, every menu item is included in the tab order, including all the sub-menu items. This behaves just like the “accessible” menus of yesteryear. Everything’s technically accessible, but it’s not very usable since it requires so much tabbing. The difference in this case though is that users don’t have to tab. They can navigate more efficiently with enter, space, arrow keys and escape. But how will users know that? That’s the way keyboard-accessible menus in software applications have always behaved, but historically web-based menus haven’t had this functionality. This menu system works using the old method, so if users don’t know about the new method they can still access the menu items.
In contrast, the YUI menu has only one tab stop. The very first menu item has tabindex=”0″, so users tab to that within the normal tab order of the web page. However, if they hit tab a second time they exit the menu. The only way to navigate within the menu is to use the new, more efficient navigation keys.
The Customized OAA menu provides a middle path between these two extremes. Each of the top-level menu items has tabindex=”0″, so users can access each of these items within the tab order, but to access dropdown menus they’ll have to use other keys. Users probably won’t even know there are dropdown menus until they press Enter, which they would normally do anyway, expecting that to take them to another web page. In this case, pressing Enter doesn’t lead to a new web page, but triggers the display of the dropdown menu.
At this point the old model (tab) doesn’t take them into the dropdown menu, so there might be some initial confusion, but most users will probably guess a down arrow might work, and it will.
Which model is best?
This would make for an interesting research project. Assemble a large sample of users who typically navigate without a mouse, randomly assign them to one of three groups, and watch them interact with one of the three menus. Which group would learn the new keyboard model first? My hunch is that it would be the OAA group. The YUI group would be forced to learn – there’s no other way to navigate. However, in a sink-or-swim situation I think some users may give up and sink (I’m flashing back to experiments on “learned helplessness” that I did with rats as an undergrad). The Simply Accessible menu users have no reason to change. What they’ve always done works, and they’ll just use that method without realizing there’s a better way. So… I like the middle path of the OAA menu. Users are gently introduced to the new way, but their survival doesn’t depend on their mastering it.
What role for the menu root? menubar vs. menu vs. navigation
I’ve been using role=”menubar” for horizontal web-based menus such as those at the top of most web pages. The Simply Accessible and OAA menus both do the same, although the original OAA menubar example, prior to my customizing it, was used in a slightly different context than for website navigation. In contrast, YUI uses role=”menu”.
In the ARIA spec, menubar is defined as “A presentation of menu that usually remains visible and is usually presented horizontally”. There’s some supplemental explanatory text accompanying that definition, none of which dissuades me from using this role. However, I’ve been challenged by a couple of folks since CSUN, both suggesting that role=”menubar” was intended for menus in web-based applications such as Google Docs, which are fundamentally different than other web menus in that they consist of functions, rather than navigation links. But that difference isn’t explicitly required by the spec, so I still think menubar is the best fit. I personally like it better than role=”menu” since each dropdown menu within the larger menu system is marked up with role=”menu”, and the overall parent widget is a fundamentally different sort of object than the dropdown menus, so it seems fitting to assign them different roles.
The bottom line: Both role=”menubar” and role=”menu” seem to work for screen readers (see the details below). They identify the widget as a menu, identify sub-menus as sub-menus, and in some cases provide additional instructions.
One problem though is that neither menubar nor menu is a landmark role. There are only eight landmark roles (application, banner, complementary, contentinfo, form, main, search, and navigation), and all screen readers recognize them and provide a means for users to jump quickly to those regions. The most relevant landmark role for a navigation menu is role=”navigation”. However, the root element on our menu is role=”menubar” or role=”menu”, and only one role is permissible per HTML element. If we were to try adding role=”navigation” to the root element in the HTML of either the Simply Accessible or YUI menus, that role will be overwritten with role=”menubar” when the page is loaded. Even if we were able to pull that off, it wouldn’t be valid since the menu also includes items with role=”menuitem”, which require an ancestor with role=”menu” or role=”menubar”.
So, the workaround I’m using is wrapping the entire menu in a container <div> with role=”navigation”.
Screen Reader Support
Screen reader users might choose to navigate to the menu using their screen reader’s landmark shortcut key (e.g., semicolon in JAWS, the letter “D” in NVDA). When they do so, their screen reader will announce “Navigation Region”, along with a name of the landmark if one is assigned (e.g., using aria-label). On each of my example menus, I’ve added aria-label=”Main Menu”, so JAWS (for example) announces “Main Menu Navigation Region”.
From here, users will draw from their knowledge or experience in deciding what to do next. They might press down arrow to enter the menu, or they might press tab. Either way, I would expect their screen reader to announce that they’ve arrived on a menubar or menu, and to provide some meta data about that menubar, such the number of top-level items it contains. JAWS currently provides a more user-friendly experience than either NVDA or VoiceOver, although I only tested the latter in OS X Snow Leopard – I haven’t upgraded to Lion yet. In JAWS, when a top-level menu item has focus, JAWS announces the name of that menu item, and announces that it has a submenu. It also says “To move through items press the up or down arrow”. It only does this once per menubar widget, assuming it doesn’t need to repeat itself with such a simple instruction. Overall, the interaction with the menu using JAWS is easy and intuitive, at least that’s true of the YUI and custom OAA menu. Curiously, JAWS doesn’t recognize the Simply Accessible Menu as a menu. Users can navigate through this menu with the tab key, and JAWS announces all the menu items as links. However, if users attempt to use the menu’s supported keystrokes, it just doesn’t work. Since the Simply Accessible Menu is coded very similarly to the others, I think these are probably just bugs rather than problems in design philosophy. The takeaway: Whichever menu you choose to implement, be sure to test carefully using mouse, keyboard, and if possible, multiple screen readers.
What about Mega Menus?
Mega Menus are ultimately the problem I’m seeking to address. Today’s dropdown menus often contain more than just lists of links—they might contain all sorts of structured content, including headings, paragraphs, images, videos, and more. Do the menu methods described in this blog post apply to mega menus, or is some alternative model required? I’ll tackle that in my next blog post. Stay tuned…