The problem with the hamburger menu and how to fix it
Tags: a11y, webdev, html, javascript
Published: 2020-09-07 09:11:47

# About

Do you have a hamburger menu on your website? You probably do. And why wouldn’t you? It helps unclutter a busy website on mobile.

However there’s a problem. It’s not accessible if you haven’t actually put the time and effort to do it so.

The good news is that this can be fixed. Let’s see how.

# The situation

Firstly, it’s safe to assume that your hamburger menu looks and acts something like this:

![GIF animation of menu expanding and collapsing at the click of a button](https://dev-to-uploads.s3.amazonaws.com/i/e7ll5fluhtqyb78t0pj9.gif)

In HTML, the menu button would look something like this:

```html
<button onclick="toggleMenuVisibility()">Menu</button>
```

How you implement `toggleMenuVisibility()` is up to you, but we will update it at some point.

# The problem

The problem now is that unless you specify as such, there’s no way for a screen reader to know if this is a button which expands a menu.

The screen reader will read the button as follows:

> Menu, button

This means that blind users, only know that this is a button called Menu and is not clear that it does what it does (i.e. expanding a menu).

This is where ARIA attributes come in. 

# The solution

For your menu button, you’ll need two attributes:

* `aria-haspopup` to announce to the screen reader that or button will show a menu

* `aria-expanded` to signify the status of our menu, expanded or collapsed

Firstly, let’s add `aria-haspopup` to our button:

```html
<button onclick="toggleMenuVisibility()" aria-haspopup="true">Menu</button>
```

Next we’ll add `aria-expanded`. We’ll default this to `false` since initially, the menu is hidden.

```html
<button onclick="toggleMenuVisibility()" aria-haspopup="true" aria-expanded="false">Menu</button>
```

After adding these two attributes, the screen reader will read the Menu button as follows:

> Menu, menu pop-up, collapsed, button

This now gives a clear indication to screen reader users that this button will expand something when clicked. Much more informative!

Finally, we need to update the status of `aria-expanded` every time the user taps the hamburger menu button so that it’s set to ` true` when the menu is open, and `false` when the menu is closed. For this, we'll need to update our `toggleMenuVisibility()` function to set our attribute:

```diff
var menuElement = document.querySelector("#menu")
+ var menuButtonElement = document.querySelector("#menu-button")

function toggleMenuVisibility(){
  var currentStatus = menuElement.getAttribute("status")
  
  if(currentStatus === "visible"){
    menuElement.setAttribute("status", "hidden")
+    menuButtonElement.setAttribute("aria-expanded", "false")
  }
  else{
    menuElement.setAttribute("status", "visible")
+    menuButtonElement.setAttribute("aria-expanded", "true")
  }
}
```

If you now open your page with a screen reader and tap on the Menu button to open the menu, the screen reader will say something along the lines of:

> Menu, menu pop-up, expanded, button

If you tap the Menu button again, once again it'll read:

> Menu, menu pop-up, collapsed, button

Perfect! Exactly what we need the screen reader to say to keep *all* our users informed.

And you should be set! Your hamburger menu should now be accessible!

# Further considerations

### 1. Provide alternative labelling for hamburger icons

If you're using a hamburger icon from FontAwesome, Bootstrap or an image, make sure you use `aria-label` and `aria-hidden` attributes to provide alternative labels for screen readers:

```html
<a href="#" aria-label="Collapse or expand the menu">
  <i class="fas fa-bars" aria-hidden="true"></i>
</a>
```

### 2. Make sure the menu has the focus after expanding it

Keyboard and screen reader users want to access the menu immediately after tapping/clicking on the Menu button. Make sure your menu has the focus immediately after expanding it.

# That’s too much work! What’s the point?

I'm going to end this article the same way I ended my previous [article on inaccessible typewriter effect](https://dev.to/savvasstephnds/the-problem-with-the-typewriter-effect-and-how-to-fix-it-2731). You have an obligation as a human first, and as a developer second, to be inclusive in your work, even your personal portfolio.  Be inclusive. Be human. 

# How about you?

Have you taken steps to make your menu more accessible? What are they and what difficulties have you faced? Let me know in the comments [or on Twitter](https://twitter.com/SavvasStephnds)!