Don't nest <nav> inside <header>. Do nest the hamburger menu button inside <nav>.
Tags: a11y, html, webdev
Published: 2021-06-12 10:26:08

This article may be provocative. Let me know what you think.

## 1. Motivation
Imagine you need to build a web site with a top app bar like this one (source: [Material Design](https://material.io/components/app-bars-top)):![Material design top app bar](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6jt03f0pgmxjlh4c3e8w.png)

And tapping the hamburger menu button on the left will open a navigation drawer (source: [Material Design](https://material.io/components/navigation-drawer)):![Material design navigation drawer](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ylcdnvpur1imucul8p0t.png)

How would you mark up an HTML document for this trio of (1) top app bar, (2) menu button, and (3) navigation drawer?

Given the standard practice of nesting `<nav>` inside `<header>` and the visual appearance of nesting the menu button inside the top app bar, my first instinct was:

```jsx
<header>
  <button type="button" aria-controls="navigation-drawer" aria-expanded="false">
    <img alt="menu" src="hamburger.svg"/>
  </button>
  <nav id="navigation-drawer">
    <ul>
      <li><a>Page 1</a></li>
      <li><a>Page 2</a></li>
    </ul>
  </nav>
</header>
```

- For `aria-controls`, see [Accessibility Developer Guide (2018)](https://www.accessibility-developer-guide.com/knowledge/aria/purpose/#tablist-using-aria).
- For `aria-expanded`, see [Silver (2019)](https://css-tricks.com/why-how-and-when-to-use-semantic-html-and-aria/#using-aria-and-javascript-together).

However, learning about accessibility, especially about *landmark roles*, my conclusion is:

```jsx
<div>
  <header></header>
  <nav>
    <button type="button" aria-controls="navigation-drawer" aria-expanded="false">
      <img alt="menu" src="hamburger.svg"/>
    </button>
    <ul id="navigation-drawer">
      <li><a>Page 1</a></li>
      <li><a>Page 2</a></li>
    </ul>
  </nav>
</div>
```

where the outer `<div>` will be styled as the top app bar, and `<ul>` will be styled with `position:fixed`, hidden initially, and toggled to be visible with the clicking of `<button>` (with `aria-expanded` turned into `true`).

Do you wonder why? Read on.

## 2. Landmark roles

Both `<header>` and `<nav>` are associated with landmark roles. To understand the best use of these elements, we need to know what landmark roles are.

### Elements with landmark roles

There are 8 HTML elements with landmark roles ([MDN Contributors 2021c](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques#landmark_roles)). 

1. `<header>` (the `banner` role)
2. `<main>` (the `main` role)
3. `<footer>` (the `contentinfo` role)
4. `<nav>` (the `navigation` role)
5. `<aside>` (the `complementary` role)
6. `<form>` (the `form` role)
7. `<form role="search">` (the `search` role)
8. `<section>` (the `region` role)

The last two in this list require some footnotes.

- `<form role="search">` explicitly specifies the landmark role of `search` with the `role` attribute, which would be redundant for the other 7 elements.
- `<section>` has a role of `region` only if it has an *[accessible name](https://www.tpgi.com/what-is-an-accessible-name/)* ([MDN Contributors 2021a](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section))*.* It's meant to be used if none of the other 7 landmark roles is appropriate.

My understanding is that a web developer should assign one of these 8 roles to each and every segment of a web page, to help screen reader users figure out the overall structure of the page.

### How screen readers behave with landmark roles

The best explanation of landmark roles that I've found is [Faulkner (2013)](https://www.tpgi.com/using-wai-aria-landmarks-2013/), cited by [Coyier (2013)](https://css-tricks.com/using-wai-aria-landmarks/), with a description of how a screen reader (JAWS version 10 and above) behaves with landmark roles.

The screen reader allows its users to cycle through landmarks with `;`, the semi-colon key. Then pressing the arrow down key will move to its child elements.

This is why all the contents on a page should be the children of a landmark role element, as [Schwerdtfeger (2013)](https://www.tpgi.com/using-wai-aria-landmarks-2013/#comment-1247) comments:

> Probably the most important rule for applying landmarks is to ensure all content resides in a landmark region to ensure no content is orphaned. This way a screen reader user can safely use landmark navigation without missing content.

Now the important bit: If a landmark element is a child of another landmark element, it is not included within the cycle order. 

This has a big implication of whether `<nav>` should be a child of `<header>` or not.

## 3. Don't nest `<nav>` inside `<header>`

Given how screen readers behave with landmark elements (as described above), if we have `<nav>` inside `<header>`, a screen reader user won't notice the presence of `<nav>` unless they decide to see the content of `<header>`.

Once I learned this, I understand why [MDN Contributors (2021b)](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure#basic_sections_of_a_document) have written the following passage for `<nav>`:

> Many web designers consider the navigation bar to be part of the header rather than a individual component, but that's not a requirement; in fact some also argue that having the two separate is better for accessibility, as screen readers can read the two features better if they are separate.

It seems to be a consensus among web developers that nesting `<nav>` inside `<header>` is neither necessary nor anti-pattern (e.g. [Devlin 2011](https://stackoverflow.com/a/4872533)).

But I personally vote for NOT nesting `<nav>` inside `<header>` for the purpose of a better user experience with screen readers.

## 4. Do nest `<button>` inside `<nav>`

Now the question is where to place `<button>`. Inside `<header>`, inside `<nav>`, or outside both?

### Rationale

[Evans (2020)](https://knowbility.org/blog/2020/accessible-slide-menus/) has an answer, saying that placing the hamburger menu button within `<nav>` "allows screen reader users to navigate directly to the navigation landmark. If the entire `<nav>` is hidden with `visibility:hidden`, there will be no navigation landmark for screen reader users to navigate to."

Initially, I didn't really understand this statement. Once I learned about landmark roles and how screen readers behave with them (as describe above in this article), however, I now fully agree.

This practice, nesting `<button>` inside `<nav>`, is also adopted by [Pickering (2017)](https://inclusive-components.design/menus-menu-buttons/) and by [Lazaris (2020)](https://www.impressivewebs.com/accessible-keyboard-friendly-hamburger-menu-slide-out-navigation/). 

### Counter-argument

But it seems that this practice is not widely accepted. 

[Akymenko (2019)](https://css-tricks.com/hamburger-menu-with-a-side-of-react-hooks-and-styled-components), a very well-written tutorial on scratch-building a hamburger menu and a navigational drawer with React, doesn't nest the hamburger menu button within `<nav>`. And none of the comments to the article mentions the nesting of the button within `<nav>` though some point out other accessibility issues.

Commenting to [Lazaris (2020)](https://www.impressivewebs.com/accessible-keyboard-friendly-hamburger-menu-slide-out-navigation/), [Gunnarsson (2020)](https://www.impressivewebs.com/accessible-keyboard-friendly-hamburger-menu-slide-out-navigation/#comment-77986) proposes to take out `<button>` out of `<nav>` by saying:

> By doing this you clearly mark the boundries of the content that is displayed when you click the button...

I initially took the side of [Gunnarsson (2020)](https://www.impressivewebs.com/accessible-keyboard-friendly-hamburger-menu-slide-out-navigation/#comment-77986) rather than [Lazaris (2020)](https://www.impressivewebs.com/accessible-keyboard-friendly-hamburger-menu-slide-out-navigation/), who didn't revise his article in response (though Gunnarsson's other suggestions were taken). Once I learned about landmark roles, however, this counter-argument isn't convincing enough because it doesn't refer to accessibility. It just relies on logic.

People argue different things about semantic HTML. But some do not support their argument from the viewpoint of accessibility. But, as I understand it, semantic HTML is first and foremost for accessibility (and then for SEO). As I argued before ([Kudamatsu 2019](https://medium.com/web-dev-survey-from-kyoto/semantic-html-as-graphic-design-without-graphics-ac98e9c2d756)), semantic HTML is graphic design without the use of graphic. I've learned that I should discount any arguments on semantic HTML if they are not based on accessibility.

## 4. Feedback welcome!

This article is a working draft. It's more for seeing whether other people agree or disagree, rather than for claiming that this is the way to go. Let me know if you think I miss something important.

## Changelog

**Oct 21, 2022 (v1.0.1)**: Edit the title.

## References

Accessibility Developer Guide (2018) "[The purpose behind the WAI-ARIA standard](https://www.accessibility-developer-guide.com/knowledge/aria/purpose/)", *Accessibility Developer Guide*, May 14, 2018 (last updated).

Akymenko, Maks (2019) "[Hamburger Menu with a Side of React Hooks and Styled Components](https://css-tricks.com/hamburger-menu-with-a-side-of-react-hooks-and-styled-components)", *CSS-Tricks*, Sep 10, 2019.

Coyier, Chris (2013) "[Using WAI-ARIA Landmarks](https://css-tricks.com/using-wai-aria-landmarks/)", *CSS-Tricks*, Feb 18, 2013. 

Devlin, Ian (2011) "[It's completely up to you....](https://stackoverflow.com/a/4872533)", *Stack Overflow*, Feb 2, 2011.

Evans, Alicia (2020) "[Let’s Focus on Slide-Out Navigation](https://knowbility.org/blog/2020/accessible-slide-menus/)", *Knowbility*, Mar 26, 2020. 

Faulkner, Steve (2013) "[Using WAI-ARIA Landmarks – 2013](https://www.tpgi.com/using-wai-aria-landmarks-2013/)", *TPGi*, Feb 12, 2013.

Gunnarsson, Birkir (2020) "[This is looking very good. A couple of usability suggestions...](https://www.impressivewebs.com/accessible-keyboard-friendly-hamburger-menu-slide-out-navigation/#comment-77986)", *Impressive Webs*, Jul 2, 2020.

Kudamatsu, Masa (2019) "[Semantic HTML as graphic design without graphics](https://medium.com/web-dev-survey-from-kyoto/semantic-html-as-graphic-design-without-graphics-ac98e9c2d756)", *Web Dev Survey from Kyoto*, Jul 11, 2019.

Lazaris, Louis (2020) "[Accessible and Keyboard-Friendly Hamburger Menu + Slide Out Navigation](https://www.impressivewebs.com/accessible-keyboard-friendly-hamburger-menu-slide-out-navigation/)", *Impressive Webs*, Jul 3, 2020.

MDN Contributors (2021a) "[<section>: The Generic Section element](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section)", *MDN Web Docs*, Jun 3 2021 (last updated).

MDN Contributors (2021b) "[Document and website structure](https://developer.mozilla.org/en-US/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure)", *MDN Web Docs*, Jun 7, 2021 (last updated). 

MDN Contributors (2021c) "[Using ARIA: Roles, states, and properties](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques)", *MDN Web Docs*, Apr 19, 2021.

Pickering, Heydon (2017) "[Menus & Menu Buttons](https://inclusive-components.design/menus-menu-buttons/)", *Inclusive Components*, May 10, 2017.

Schwerdtfeger, Rich. (2013) "[Probably the most important rule for applying landmarks is...](https://www.tpgi.com/using-wai-aria-landmarks-2013/#comment-1247)", *TPGi*, Feb 12, 2013.

Silver, Adam (2019) "[Why, How, and When to Use Semantic HTML and ARIA](https://css-tricks.com/why-how-and-when-to-use-semantic-html-and-aria/)", *CSS-Tricks*, May 7, 2019.