How to build an accessible navigation menu
Tags: frontend, a11y, beginners, webdev
Published: 2023-12-06 12:02:17

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>
```
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>
```

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](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/menubar_role#description) `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>
```

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 <a> 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](https://www.w3.org/WAI/ARIA/apg/practices/read-me-first/)

## 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>
```
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>
```
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.

{% embed https://www.loom.com/share/8f280344f94c4db588dd1111952c72ee?sid=90fa8429-2d2d-41cb-b35c-328d072de532 %}

Here's the link to the [codepen](https://codepen.io/leezee/pen/YzBaRwg) 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 ↓
{% embed https://dev.to/ilizette/how-i-test-a-website-for-accessibility-167g %}

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! 😁

<img width="100%" style="width:100%" src="https://media.giphy.com/media/B4AgWgg9DIBsAwv0kL/giphy.gif">