DEV Community

Cover image for How to build an accessible navigation menu
Elizabeth
Elizabeth

Posted on

How to build an accessible navigation menu

Hey there! Today, we're looking into how to build an accessible menu. I decided to write this article because recently, while running an accessibility test on some websites, including some of my past projects, one common issue was that navigating submenus with just a keyboard or screen reader was trickier than it should be.

This article aims to show you what to do when building a navigation and fix any oopsies you might have made. I have also added an example of a simple menu. Ready to dive in? πŸ˜…

Semantic HTML and aria

Optimizing your code for readability is as simple as choosing the right HTML tags. Consider this transformation:



<nav>
 <ul>
   <li><a href="#">list item 1</a></li>
   <li><a href="#">list item 2</a></li>
   <li><a href="#">list item 3</a></li>
 </ul>
</nav>


Enter fullscreen mode Exit fullscreen mode

which is far more legible compared to:



<div>
  <div>
    <a href="#">list item 1</a>
    <a href="#">list item 2</a>
    <a href="#">list item 3</a>
  </div>
</div>


Enter fullscreen mode Exit fullscreen mode

Not only is the first example more readable, but it also ensures that a screen reader lets the user know that they're currently on the navigation.

However, sometimes using the right semantic element might not explain the role of our element properly, This is where using aria and roles shine. In the first example, we have a <ul> which is currently a list, we don't want the browser to see it as a list, the ul is supposed to act as a menubar so we can improve the code by adding a role="menubar", a menubar can have a menuitem, menuradio, or menuitemcheckbox. In our case, we only need a menuitem.



<nav>
 <ul role="menubar">
   <li role="none"><a href="#" role="menuitem">list item 1</a></li>
   <li role="none"><a href="#" role="menuitem">list item 2</a></li>
   <li role="none"><a href="#" role="menuitem">list item 3</a></li>
 </ul>
</nav>


Enter fullscreen mode Exit fullscreen mode

In the updated code I added a role="none" to the li tag, this is because the li will be acting as a container for this example, the element is explicitly designated as a menuitem.

Please note that there's such a thing as using the wrong aria, if you don't use aria correctly it could break your accessibility. A rule of thumb is "No aria is better than bad aria". You can read more about this here

Code structure for focus order

While you can always move things with CSS when building an accessible platform you need to ensure your elements are structured as they appear. A Properly structured code helps in managing the focus order. When users press the Tab key to move through interactive elements, the focus should follow a logical order. Without proper structure, the focus might jump unpredictably, making navigation difficult.

This is also important when working with a submenu, for example: if a user has to tab through all the menuitems before they can get to a submenu then the navigation isn't friendly. Instead of having a code like this:



<nav>
 <ul role="menubar" id="mainmenu">
   <li role="none"><a href="#" role="menuitem">list item 1</a></li>
   <li role="none"><a href="#" role="menuitem">list item 2</a></li>
   <li role="none"><a href="#" role="menuitem">list item 3</a></li>
 </ul>
<ul id="submenuList1">
  <li role="none"><a href="#" role="menuitem">sub list item 1</a></li>
<li role="none"><a href="#" role="menuitem">sub list item 2</a></li>
</ul>
</nav>


Enter fullscreen mode Exit fullscreen mode

We can do this:



<nav>
 <ul role="menubar">
   <li role="menuitem">List item 1
   <ul role="menu">
     <li role="none"><a href="#" role="menuitem">sub list item 1</a></li>
     <li role="none"><a href="#" role="menuitem">sub list item 2</a></li>
   </ul>
  </li>
   <li role="none"><a href="#" role="menuitem">list item 2</a></li>
   <li role="none"><a href="#" role="menuitem">list item 3</a></li>
 </ul>
</nav>


Enter fullscreen mode Exit fullscreen mode

Remember, you can always move things with CSS, but if your HTML is not structured, the experience will be different for keyboard users and screen readers. Here's an example of me using a screen reader to access a menu with a submenu.

Here's the link to the codepen you can test it on a keyboard and screen reader.

In a future article, I'll be sharing how to test with screen readers

Conlusion

Almost every web platform has a menu, it's what gives users an idea of what to expect. If some users cannot access it then your platform is not complete. You need to ensure that the experience is easy for everyone by ensuring that:

  • A user can navigate the menubar without using a mouse
  • A user can open and close the submenu without the mouse. for example: when a user clicks on the enter/return or the space key it should toggle the submenu.
  • A screen reader can read to the user that they're on a menuitem or a submenu.

If you want to know how to run a full test for accessibility, I wrote an article on it. You can find it ↓

It is our duty to make the internet experience awesome for everyone.


Thank you for reading this article. If you liked it, feel free to give it a thumbs up and share it. Drop your thoughts in the commentsβ€”I'm curious about what you think. Got a specific accessibility topic in mind? Tell me in the comments, and I'll try my hand at it. Until next time, have an awesome week or weekend! 😁

Top comments (4)

Collapse
 
framemuse profile image
Valery Zinchenko

Could you explain why not just do it this way?

<nav>
<a href= ...>
</nav>
Enter fullscreen mode Exit fullscreen mode
Collapse
 
rahmaut profile image
Rahmaut | πŸ‡΅πŸ‡Έ • Edited

because:
you can have limitless <a> and with your sight you know how many <a> in the list. But using <li> can help screen reader user to have an overview how many list are them without run through everything manually. It give sense of menu overview for non sighted user. It will be announced "list of x item, item y of x". Imagine you have 100 link and you are not aware that there are 100 of them.

cmiiw

Collapse
 
framemuse profile image
Valery Zinchenko

I doubt I would have more than 5 links in a Header navigation

Thread Thread
 
rahmaut profile image
Rahmaut | πŸ‡΅πŸ‡Έ

Well, sighted users can easily know it consists of 5 links just from the layout. By using a list, Screen reader users can expect how many menu items are available since the first keyboard focus lands on the first nav bar menu. Imagine skimming without seeing. We sighted users skim just by scrolling in less than 5 seconds.