42

We are in the process of implementing (i.e. adding) WAI-ARIA support to the main navigation menu of a web portal. Menu is the one shown here:

Navigation menu screenshot

Menu is implemented by means of classic <ul> / <li> / <a> DOM tree, styled with CSS to look like horizontal tabs.

What is a WAI-ARIA compliant implementation for such a widget?

I've read many parts of most recent WAI-ARIA specs from w3org for a general understanding, taxonomy, and so on. Then I've read about several examples of UI widget implementations. I could not find any example specifically targetd at such a CSS navigation menu. The closest widgets I've always found around are the Menu, the MenuBar, and the TabPanel. Of course I also looked in Free ARIA Community group (where this question was originally posted).

I'd say that none of those widgets exactly match a (CSS) navigation menu. As an example, TabPanel may control some content in the page (--> aria-controls), maybe MenuBar too; but I'm not at all sure that a navigation menu controls content in the page (it controls the next page to show). Without going further, there are some other differences as well. References are at the end of the post. If anyone as better (or more fit) examples of navigation menu, we'd be glad to know about them.

References

superjos
  • 12,189
  • 6
  • 89
  • 134

5 Answers5

76

A possible implementation would be:

HTML structure:

<div> <!-- Outer wrapper -->
  <ul> <!-- Main navigation bar container -->
    <li> <!-- First-level item without submenu -->
      <a> <!-- Destination URL -->
      </a>
    </li>
    <li> <!-- First-level item with submenu -->
      <a> <!-- Destination URL -->
      </a>
      <ul> <!-- Second-level menu container -->
        <li> <!-- Second-level item -->
          <a>
          </a> <!-- Destination URL -->
        </li>
      </ul>
    </li>
  </ul>
</div>

Roles:

  • role=”navigation” for outer wrapper <div>
  • role="menubar" for <ul> navigation bar container
  • role="menu" for second-level <ul> containers
  • role="presentation" for first- and second-level <li> menu items (they are not needed in the exposed accessible menubar structure)
  • role="menuitem" for first- and second-level <a> menu items

Properties:

  • aria-haspopup="true" for first-level <a> menu items having a submenu
  • aria-labelledby="ID of previous <a> menu item" for second-level <ul> containers

States:

  • aria-selected="true" on currently visited first- or second-level <a> item; aria-selected="false" on the other <a> items. That is to enforce the concept “selected <==> current page”
  • aria-expanded="true/false" for second-level <ul> containers
  • aria-hidden="true/false" for second-level <ul> containers
  • aria-activedescendant="" for main <ul> navigation bar container. This is an alternative to working with tabindex
  • tabindex=0 on currently visited <a> item; tabindex=-1 on the other <a> items. That is in order to first focus on the current page when tabbing to the navigation bar. It is an alternative to working with aria-activedescendant

Keyboard:

  • Tab: Move focus in/out of the menu from other points in the web application.
  • Shift+Tab: Move focus in/out of the menu from other points in the web application, in the reversed order.
  • Right arrow: Next navigation bar item
  • Left arrow: Previous navigation bar item
  • Enter: Activate currently focused item (i.e. navigate to corresponding URL)
  • Space: Activate currently focused item (i.e. navigate to corresponding URL)

Aug/2014: aria-selected Vs menuitem

In reply to @Joshua Muheim comment: now I can see from here, as well as from his reference, that aria-selected attribute is not allowed for menuitem role.
As I read from this recent SO answer there are some solutions given the current state of things, and there is a new proposed attribute too.

Community
  • 1
  • 1
superjos
  • 12,189
  • 6
  • 89
  • 134
  • 3
    I was almost ready to give up on the aria specs being poorly thought out until I read your answer. For me, it was the "presentation" role I was missing from my menu, which resulted in strange behaviour like each menu item being read out as being "1 of 1" instead of "1 of [length]". Most of the examples I've seen online result in this undesirable behaviour and I haven't found any that say `ul[role=menu] > li[role=presentation] > a[role=menuitem]` other than your answer. Well done. – Iain Fraser Dec 10 '12 at 00:47
  • Actually, the "1 of 1" problem was when I was trying `ul[role=menu] > li > a[role=menuitem]`. To be sure, most people were recommending `ul[role=menu] > li[role=menuitem] > a`, which didn't work at all! It would read the menu items, but as there was no link focussed, you couldn't go anywhere with them. – Iain Fraser Dec 10 '12 at 00:53
  • glad it helped! As far as I got, the need for xxx[role=presentation] holds everytime you insert some (nested) nodes only for *aestetichal* purposes, i.e. positioning, showing/hiding, background coloring, and so on. But those nodes mean nothing from the *content* point of view, so you mark them for whatever Accessibility Tool. – superjos Dec 10 '12 at 11:43
  • Does an `application` role need to be defined as well? Also, when using screen readers (SR) such as JAWS elements with `menuitem` roles (such as anchor links) will be ignored in the SR shortcut lists. – skube Jun 16 '14 at 15:24
  • In that scenario, we thought the `application` role was not necessary. Regarding `menuitem` roles, I remember that was the best match we found, and I think it was also the most common choice we saw around. – superjos Jun 17 '14 at 16:02
  • A recent update: specs are now written in a more *developer friendly* way, as said in http://html5doctor.com/using-aria-in-html – superjos Jun 26 '14 at 10:16
  • I don't see that `aria-selected` can be used in aria menus. http://www.w3.org/TR/wai-aria/states_and_properties#aria-selected This seems to be a common mistake, and I don't know a better way to tell the selected state but adding some visually hidden text like "active item". – Joshua Muheim Sep 11 '14 at 14:08
  • 1
    If some of the top-level menu items are not links but are buttons only used to open a submenu, how should they be treated? – jbyrd Aug 31 '15 at 16:46
  • Why `role="menu"` not `role="submenu"`? – evolutionxbox Dec 20 '17 at 17:21
  • There's an error in your answer: `aria-expanded="true/false"` is not intended for `
      ` containers, it's intended for links/buttons that trigger the expansion.
    – catamphetamine Dec 09 '18 at 11:10
  • thanks for pointing that out. Is there a link to specs/docs regarding this particular subject? – superjos Dec 10 '18 at 13:15
0

You can get a menu to announce 'X of Y' information by adding the aria-posinset and aria-setsize attributes to the elements with role=menuitem.

TylerH
  • 20,799
  • 66
  • 75
  • 101
  • Thanks for sharing that. I think it might be helpful to others if the menu DOM changes dinamically. I can read from [here](http://www.w3.org/TR/wai-aria/states_and_properties#aria-posinset) that "Not required if all elements in the set are present in the DOM" – superjos Dec 09 '13 at 14:56
  • This is more of a comment than an answer. – TylerH Oct 19 '21 at 15:12
0

The ARIA design patterns provide expected UI behaviour for a range of custom controls http://www.w3.org/TR/wai-aria-practices/#aria_ex use of esc key to close and return to triggering element upon close is standard UI across desktop and web. Try it on any Google docs app (for example).

Volker E.
  • 5,911
  • 11
  • 47
  • 64
Steve Faulkner
  • 2,572
  • 15
  • 17
-1

+Escape key should close an open menu and return focus to the element that opens it.

user810937
  • 54
  • 2
  • It's been some time now since I last thought about those features. At a first glance, using Escape key to close an open menu seems like a good fit (I don't remember if I already saw that mentioned during my search). I'm not sure though what should happen after closing the menu with Esc: your proposal (return focus to element that opens it) does not seem ok to me. – superjos Sep 09 '13 at 10:41
  • 1
    Escape is a standard to close. http://access.aol.com/dhtml-style-guide-working-group/#menu – user810937 Aug 20 '14 at 19:48
  • This is more of a comment than an answer. – TylerH Oct 19 '21 at 15:13
-1

Escape to close is a standard going way back, it is expected behavior by many users.