6. Interactive WAI-ARIA (Advanced)

Menu Bars

Menu bars are typically presented horizontally across the top of a website or web application. They contain links to key areas of the website or application. They function as toggles that open submenus or function as both links and toggles. Menu bars remain in view across the entire website or application.

Roles, states, and properties used in a menu bar

  • aria-hidden = [true|false]
  • role = “menubar”
  • role = “menu”
  • role = “menuitem”
  • aria-labelledby = “[instruction div id]”
  • aria-label = [link text]
  • tabindex = [0 | -1]
  • aria-haspopup = “true”
  • aria-expanded = “[true|false]”
  • aria-selected = “[true|false]”

Suggested Reading: For more about accessible menus, see ARIA Authoring Practices Guide: Menus or Menu Bar.

The following JSFiddle presents a typical menu bar widget with a variety of sub menus. Review the JavaScript and HTML markup. Test the menu bar presented under the Result tab with ChromeVox to understand how it functions without any accessibility features added. You can work in JSFiddle itself by clicking the “Edit in JSFiddle” link at the top, right-hand side, copying the accessibility/WAI-ARIA code described below to fix the accessibility of the menu bar before completing Activity 12 on the page that follows.

First, provide some instructions on how to use the menu with a keyboard and add them to the default options.

Hide the instructions from screen readers until needed, adding aria-hidden="true" to the instructions <div> defined when the menu is initialized.

Add role="menubar" to the top level <ul> in the menu. Make that <ul> keyboard focusable with tabindex="0", so it reads the instructions while in focus and referenced with aria-labelledby.

For all the menu items in the menu bar that have submenus, add role="menu" to their <ul> and hide them by default using aria-hidden="true". This can be located after the $elem.find('ul:eq(0)') block presented immediately above.

Hide the links in the menu items from screen readers by default using tabindex="-1" and setting aria-hidden="true".

Set up the menu items throughout the menu using role="menuitem". Also, remove keyboard access by default with tabindex="-1". Next, label each menu item with the text of the associated link using aria-label="[$link.text]".

For each of the menu items that has a submenu, add aria-haspopup="true" to announce the presence of the submenu, and set its default state to “collapsed” by adding aria-expanded="false".

When a menu item is marked selected, also add aria-selected="true" and add keyboard access back to the menu item with tabindex="0".

Add keyboard access back to menu items using tabindex="0".

Reference the keyboard access class, where mouse events are defined in the onKeyDown function, described below.

In the showSubMenu function, add aria-expanded="true" submenus when they are expanded, remove keyboard access from the submenu container with tabindex="-1". Then, make the submenu visible with aria-hidden="false".

In the hideSubMenu function, set aria-expanded="false", hide submenus with aria-hidden="true", and remove keyboard access with tabindex="-1" when a submenu is closed.

When the collapseAll function is called, to collapse any open menus, reverse all attributes defining the element as open, reverting to aria-hidden="true", aria-expanded="false" and re-adding keyboard access with tabindex="0" so it can be opened again.

Adding Keyboard Operability

Menu bar keyboard functionality can be complex, particularly with large menus with multiple levels of submenus, and they can include redundant keys that perform the same function. The W3C defines suggested keyboard interaction for a menu bar as follows:

Menu Bar Keyboard Interaction

This description of keyboard behaviours assumes the following:

  1. A horizontal menubar containing several menuitem elements.
  2. All items in the menubar have child submenus that contain multiple vertically arranged items.
  3. Some of the menuitem elements in the submenus have child submenus with items that are also vertically arranged.

When reading the following descriptions, also keep in mind these items:

  1. Focusable elements, which may have role menuitem, menuitemradio, or menuitemcheckbox, are referred to as items.
  2. If a behaviour applies to only certain types of items, e.g., menuitem elements, the specific role name is used.
  3. Submenus, also known as pop-up menus, are elements with role menu.
  4. Except where noted, menus opened from a menu button behave the same as menus opened from a menu bar.
  • When a menu opens, or when a menubar receives focus, keyboard focus is placed on the first item. All items are focusable as described in 5.6 Keyboard Navigation Inside Components.
  • Enter:
    • When focus is on a menuitem that has a submenu, opens the submenu and places focus on its first item.
    • Otherwise, activates the item and closes the menu.
  • Space:
    • (Optional): When focus is on a menuitemcheckbox, changes the state without closing the menu.
    • (Optional): When focus is on a menuitemradio that is not checked, without closing the menu, checks the focused menuitemradio and unchecks any other checked menuitemradio element in the same group.
    • (Optional): When focus is on a menuitem that has a submenu, opens the submenu and places focus on its first item.
    • (Optional): When focus is on a menuitem that does not have a submenu, activates the menuitem and closes the menu.
  • Down Arrow:
    • When focus is on a menuitem in a menubar, opens its submenu and places focus on the first item in the submenu.
    • When focus is in a menu, moves focus to the next item, optionally wrapping from the last to the first.
  • Up Arrow:
    • When focus is in a menu, moves focus to the previous item, optionally wrapping from the first to the last.
    • (Optional): When focus is on a menuitem in a menubar, opens its submenu and places focus on the last item in the submenu.
  • Right Arrow:
    • When focus is in a menubar, moves focus to the next item, optionally wrapping from the last to the first.
    • When focus is in a menu and on a menuitem that has a submenu, opens the submenu and places focus on its first item.
    • When focus is in a menu and on an item that does not have a submenu, performs the following 3 actions:
      1. Closes the submenu and any parent menus.
      2. Moves focus to the next menuitem in the menubar.
      3. Either: (Recommended) opens the submenu of that menuitem without moving focus into the submenu, or opens the submenu of that menuitem and places focus on the first item in the submenu.

      Note that if the menubar were not present, e.g., the menus were opened from a menubutton, Right Arrow would not do anything when focus is on an item that does not have a submenu.

  • Left Arrow:
    • When focus is in a menubar, moves focus to the previous item, optionally wrapping from the last to the first.
    • When focus is in a submenu of an item in a menu, closes the submenu and returns focus to the parent menuitem.
    • When focus is in a submenu of an item in a menubar, performs the following 3 actions:
      1. Closes the submenu.
      2. Moves focus to the previous menuitem in the menubar.
      3. Either: (Recommended) opens the submenu of that menuitem without moving focus into the submenu, or opens the submenu of that menuitem and places focus on the first item in the submenu.
  • Home: If arrow key wrapping is not supported, moves focus to the first item in the current menu or menubar.
  • End: If arrow key wrapping is not supported, moves focus to the last item in the current menu or menubar.
  • Any key that corresponds to a printable character (Optional): Move focus to the next menu item in the current menu whose label begins with that printable character.
  • Escape: Close the menu that contains focus and return focus to the element or context, e.g., menu button or parent menuitem, from which the menu was opened.
  • Tab: Moves focus to the next element in the tab sequence, and if the item that had focus is not in a menubar, closes its menu and all open parent menu containers.
  • Shift + Tab: Moves focus to the previous element in the tab sequence, and if the item that had focus is not in a menubar, closes its menu and all open parent menu containers.
Note:
  1. Disabled menu items are focusable but cannot be activated.
  2. A separator in a menu is not focusable or interactive.
  3. If a menu is opened or a menu bar receives focus as a result of a context action, Esc or Enter may return focus to the invoking context. For example, a rich text editor may have a menu bar that receives focus when a shortcut key, e.g., Alt+F10, is pressed while editing. In this case, pressing Esc or activating a command from the menu may return focus to the editor.
  4. Although it is recommended that authors avoid doing so, some implementations of navigation menu bars may have menuitem elements that both perform a function and open a submenu. In such implementations, Enter and Space bar perform a navigation function, e.g., load new content, while Down Arrow, in a horizontal menu bar, opens the submenu associated with that same menuitem.
  5. When items in a menubar are arranged vertically and items in menu containers are arranged horizontally:
    1. Down Arrow performs as Right Arrow is described above, and vice versa.
    2. Up Arrow performs as Left Arrow is described above, and vice versa.

Source: W3C ARIA Authoring Practices Guide

Here we have implemented a subset of the keyboard interaction W3C recommends in an onKeyDown() function that is called when event handlers are set up for menu items. These keys include Left and Right arrows, Up and Down arrows, the Space bar and Enter keys, and Tab and Esc keys. Copy the following function into the ik_menu.js file, near the end, to add keyboard operability to the menu.

Accessible Menu Bar in Action

Watch the following video showing ChromeVox interacting with a menu bar. The Tab key is used to navigate into the menu bar, to the first menu item, and to exit the menu bar. Left and Right arrow keys are used to move across the top level menu items. Up and Down arrows are used to move into and out of a submenu and to move between menu items in a submenu. The Space bar or Enter key are used to activate a menu item. The Esc key closes the current submenu. Aim to have the menu bar you update in the activity on the next page operate and announce itself like the one in the video.

Video: Accessible Menu Bar

License

Icon for the Creative Commons Attribution-ShareAlike 4.0 International License

Web Accessibility for Developers Copyright © 2019 by The Chang School, Toronto Metropolitan University is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License, except where otherwise noted.

Share This Book