A11y Front-end Roadmap #3 - Navigation

A11y Front-end Roadmap #3 - Navigation

Bad navigation means unusable appliation

Go back to A11y Roadmap Index

Navigation is essential for users to explore the website or application, and a well-crafted navigation system helps both assistive technology and the overall user experience (while also improving your SEO).

1. Semantic HTML for Navigation

Using semantic HTML is the first step in creating accessible navigation. The <nav> element plays a critical role in this process:

1.1 Navigation Element

  • Use <nav>: Wrap your navigation links within a <nav> element to indicate that this section contains navigation links.

  • Specify <nav> ID: It's not strictly required, but having an ID to address the navigation within the DOM is beneficial.

  • Label <nav> Appropriately: There can be multiple <nav> elements on your page, so it's crucial to identify each one. Assistive technologies present all navigation groups in a single box, and labeling allows users to choose effortlessly between them.

<nav id="main-nav-menu" aria-label="Main menu">
    ... your links ...
</nav>

1.2 Menu Items List

It's almost time to add your links to the menu. I suggest using the <ul> element to group your links instead of listing them one after the other. <ul> conveys additional information about its content, allowing assistive technologies to read out loud how many items it contains and which one the user is currently focused on. You can also use <ol>, but it should only be used when your links follow a specific order.

<nav id="main-nav-menu" aria-label="Main menu">
    <ul>
        <li>...</li>
    </ul>
</nav>

For the links, we use anchor elements, as they allow for navigation. To work properly, anchors require the href attribute: via javascript it is possible to direct navigation towards a certain url, but without this attribute we endhaving an unfocusable element, so not activable via keyboard.

Having many links grouped together, suggesting the current active one could be greatly useful. You can specify your current page in two ways, both equally easy to implement:

  1. Remove the link and use plain text instead, adding hidden text specifying “Current page: ”. This way, your menu item will not be focusable or clickable. In the example, I'm using the “visually-hidden method,” which you can find in [link].

  2. Keep the anchor element but add the aria-current attribute. This will keep the anchor focusable, but assistive technologies will recognize it as the current page (and screen readers will announce it as such).

The aria-current attribute can have multiple values. In our case, only a couple could be useful:

  • true/false: Use this generic option only if it's not possible to use a more meaningful one. To avoid redundancy in screen reading, it's better to remove the attribute altogether if the value should be “false”.

  • "page": Represents the current page within a set of pages and can also be used for elements like breadcrumbs.

  • "step": For cases where main navigation uses an <ol> instead of <ul>. This is rare for a main menu but can be more common for secondary navs.

I know it may sound trivial, but make sure that no more than one item in the <nav> has “aria-current”

<nav id="main-nav-menu" aria-label="Main menu">
    <ul>
        <li>
            <span class="visually-hidden">Current page: </span>
            Page 1
        </li>
        <li>
            <a href="page.htm" aria-current="page">
                Page 2
            </a>
        </li>
    </ul>
</nav>

2. Keyboard Accessibility

Ensuring that users can navigate your website using only a keyboard is a fundamental principle of accessibility and a logical issue: why create a navigation menu if it cannot be navigated? This includes:

  • Tab Navigation: Users should be able to navigate through links and buttons using the Tab key. Ensure that all interactive elements are focusable (remember to specify a href attribute, as noted before).

  • Visible Focus Styles: Provide visible focus styles (e.g., outlines or highlights) to indicate which element is currently selected. In order to keep everything neat and clear, we’ll avooid discussing styles and UX: keep in mind that design should also align with WCAG requirements, such as contrast, font size, weight, line height, and focused state—probably too much for the scope of this article.

a:focus, button:focus, a:focus-visible, button:focus-visible {
    outline: 2px solid #0056b3; /* Example focus style */
    outline-offset: 2px;
}

Link text should be descriptive and meaningful, allowing users to understand where each link will take them. Avoid generic phrases like "click here" or "read more". It should also be coherent and consistent with the title of the target page.

<!-- Poor Link Text -->
<a href="services.html">Click here</a>

<!-- Good Link Text -->
<a href="services.html">View Our Services</a>

Not all links require icons, but it can be pretty common. We will discuss icons in the “images” section [link], but briefly consider adding the alt attribute if there is no text inside the button or in its aria-label attribute, or use role="presentation" if the icon is purely decorative.

4. Quick Take on Responsiveness

Nowadays we cannot avoid responsiveness. It doesn't matter if the application is meant to be used only on desktops or large displays: if a user requires a greater zoom level (WCAG requires zoom levels up to 400%), our detailed menu must still be usable on small viewports. Ensure that your design considers this before making extensive efforts. Also, consider a minimal toggle (like a hamburger icon) to toggle visibility on smaller screens. A more detailed explanation of this requirement in the Reflow article.

5. Other <nav> Elements on the Page

Navigation elements are not exclusive to the main navigation. By definition, <nav> represents a section of a page that provides navigation links. You can also use them for tables of contents, indexes, sitemaps, and footer navigations. Just make sure to label each one meaningfully and uniquely; you can use the aria-label attribute or aria-labelledby pointing to a heading ID.

6. What More?

What we've covered here is just a basic main menu—no fancy stuff, no dropdowns, no multilevels. We will explore these features in separate articles: divide et impera. When implementing complex navigations, many other factors must be considered, but what we've done here should be enough to understand the basic principles and work for small-sized menus. If you want to dive deeper into implementing toggles and why certain elements are used, take a read ,at [link].

A11y Front-end Roadmap Table of contents