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 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 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>
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.
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)
Could you explain why not just do it this way?
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
I doubt I would have more than 5 links in a Header navigation
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.