To save space, mobile navigation is often concealed behind “hamburger” menu buttons. For accessibility, these should be well labeled and communicate change of open/closed state via the aria-expanded attribute.

How it looks

Closed state

image of mobile navigation in closed state

Open state

image of mobile navigation in open state

The code

<!-- the closed state -->
<nav role="navigation" class="navigation-wrapper">
<button class="mobile-nav nav-closed" aria-expanded="false">
<span class="sr-only">Navigation Menu</span>
</button>
<ul hidden>
<!-- Navigation list items here -->
</ul>
</nav>

<!-- the open state -->
<nav role="navigation" class="navigation-wrapper">
<button class="mobile-nav nav-open" aria-expanded="true">
<span class="sr-only">Navigation Menu</span>
</button>
<ul>
<!-- Navigation list items here -->
</ul>
</nav>

(Code is elided.)

Notes

  • The button appears within the navigation region. This is so that screen reader users can still reach the landmark and activate the button to reveal the links.
  • In the closed state, the button has aria-expanded="false" and the list takes hidden to hide it both visually and to screen reader users. This also makes sure the list item links are not focusable while the menu is hidden.
  • A text label of “Navigation Menu” is provided but only invisibly. This means screen reader users know what the button is for. The special sr-only class provides properties that hide the element visually but not to screen readers.
  • In the open state, aria-expanded is switched to true.

sr-only class

.sr-only {
position: absolute !important;
clip: rect(1px, 1px, 1px, 1px);
padding:0 !important;
border:0 !important;
height: 1px !important;
width: 1px !important;
overflow: hidden;
}