Code examples

Use semantic HTML

This semantic HTML contains all accessibility features by default.

<a href="#nav-example">Skip to example navigation</a>
<a href="#">Not the navigation</a>
<nav tabindex="-1" class="nav-example" id="nav-example">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about/">About</a></li>
    <li><a href="/contact/">Contact</a></li>
    <li><button aria-haspopup="true">Sign in</button></li>
  </ul>
</nav>
Skip to example navigation Not the navigation

Keep custom menus as simple as possible

Use semantic elements where possible.

<nav id="example-expanding-nav" class="menu">
  <ul>
    <li>
      <a class="home" href="/">
        Home
      </a>
    </li>
    <li class="expander-group">
      <button type="button"
              class="menu expander-toggle"
              aria-expanded="false"
              aria-haspopup="true">
        Menu
      </button>

      <ul class="subnav expander-content">
        <li>
          <a href="/about/">About</a>
          <button type="button"
                  class="subnav expander-toggle"
                  aria-expanded="false"
                  aria-haspopup="true">
            <span class="hidden">About</span>
          </button>

          <ul class="expander-content">
            <li>
              <a href="/history/">Our history</a>
            </li>
            <li>
              <a href="/values/">Our values</a>
            </li>
          </ul>

        </li>
        <li>
          <a href="/contact">Contact</a>
        </li>
      </ul>
    </li>
  </ul>
</nav>

When you can’t use semantic HTML

This custom navigation requires extra attributes.

<div role="navigation">
  <ul>
    <li><a href="/">Website name</a></li>
    <li><a href="/about/">About</a></li>
    <li><a href="/contact/">Contact</a></li>
  <ul/>
</div>

Multiple navigation elements

When there is more than one navigation element, they must have a name.

<nav tabindex="-1" id="nav" aria-label="Main">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/about/">About</a></li>
    <li><a href="/contact/">Contact</a></li>
  <ul/>
</nav>

<h2 id="cat-heading">Categories</h2>
<nav id="cat-nav" aria-labelledby="#cat-heading">
  <ul>
    <li><a href="/alpha/">Alpha</a></li>
    <li><a href="/bravo/">Bravo</a></li>
    <li><a href="/charlie/">Charlie</a></li>
  <ul/>
</nav>

<footer>
  <nav aria-label="Site map">
    <ul>
      <li><a href="/">Home</a></li>
      <li><a href="/about/">About</a></li>
      <li><a href="/contact/">Contact</a></li>
    <ul/>
  </nav>
</footer>

Developer notes

Name

  • If there are multiple <nav> elements (site menu, pagination, categories) it may be helpful to name them
    • Use aria-label="Menu name" when there is not a visible nav title.
    • aria-describedby="menu-name-id" can be used when the nav title is a visible heading.

Role

  • Identifies itself as navigation
  • DO NOT add ‘menu’ or ‘option’ roles with arrow key event listeners unless you’re building an actual application like Gmail.

Focus

  • When skip links are used, add tabindex="-1" so that focus can move to the nav element, (not just bring it into view).

Further Reading