Search code examples
navigationaccessibilitywcag

Accessibility Regarding href="#"


I'm building out a site (in WordPress, for context) that needs to be WCAG compliant. I have a main navigation built out to be fully keyboard-navigable, including toggling submenus.

The issue that I'm running into is: of my navigation items that contain a submenu, some actually link to a page, while others use href="#", as they contain a submenu but don't actually link anywhere.

Ordinarily I'd use an aria-label on the navigation items that use href="#", but since they're auto-generated (by WordPress) I can't do this.

Does anyone have any suggestions? Is this even a relevant WCAG issue? Each of the href="#" navigation items are followed by a chevron (to toggle their submenu) which contains an arial-label of "Toggle submenu". Is that good enough?

Thanks!

Edit: The particular task for which I was trying to get this question answered has been put on hold. Once it's resolved I can update this question with the solution we pursued. I'm marking @slugolicious's answer as preferred because in his comments he provides a logical explanation as to why keeping the current system of inconsistent top-level navigation items is inadvisable.


Solution

  • I can't speak to wordpress but can comment on the html that should be generated, but some of what is generated depends on the behavior you want.

    Do you want the user to open the menu and arrow up/down through the list or do you want them to tab through the list?

    The former requires you to manage the focus yourself (keyboard handler for the arrow keys and maintaining the tabindex attribute) whereas the latter is much simpler - the browser can handle tabbing through the links in the menu.

    Usually, if your menu is for navigation, then the latter is desired.

    For the former (arrow key navigation), the menu roles (menu, menuitem) and attributes (aria-haspopup) should be used. When a screen reader sees those properties, it tells the user to use the arrow keys to navigate. If you have a menuitem that has a submenu, then that menuitem should have aria-haspopup specified.

    For the latter (tab key navigation), do not use any of the aforementioned menu roles. Rather, your menu should just be a list (<ul>) of links (with the list normally having list-style:none). If any of your list items have a submenu, they should contain a sublist (nested <ul>) and the list item should have the aria-expanded attribute.

    Regarding the chevron for the submenus, is the chevron a separate tab stop?

    Update to answer additional question asked by @LCW in the first comment of this answer.

    aria-expanded goes on the element that you select to display the submenu, so in your case, it would be the chevron itself, at least from what I understand about your description. It sounds like if you select a link, it goes to another page, but if you select the chevron, it opens a submenu under that item? If so, then your code would be something like this:

    <nav>
      <ul>
        <li>
          <a>menu item 1</a>
        </li>
        <li>
          <a>menu item 2</a>
          <button aria-expanded="false">chevron</button>
          <ul style="display: none">
            <li>
              <a>submenu item 1</a>
            </li>
            <li>
              <a>submenu item 2</a>
            </li>
          </ul>
        </li>
        <li>
          <a>menu item 3</a>
        </li>
      </ul>
    </nav>
    

    The chevron button has aria-expanded="false" initially and when you selected it, you should toggle the value to "true" and unhide the submenu. You can see a similar example of this on the Abercrombie & Fitch shopping page, https://www.abercrombie.com/shop/us. However, A&F hide the chevron until you TAB to it. Mouse users will never see it because the submenu opens on mouse hover. They have aria-expanded set on their chevron too.