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):
And tapping the hamburger menu button on the left will open a navigation drawer (source: Material Design):
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:
<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). - For
aria-expanded
, see Silver (2019).
However, learning about accessibility, especially about landmark roles, my conclusion is:
<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).
-
<header>
(thebanner
role) -
<main>
(themain
role) -
<footer>
(thecontentinfo
role) -
<nav>
(thenavigation
role) -
<aside>
(thecomplementary
role) -
<form>
(theform
role) -
<form role="search">
(thesearch
role) -
<section>
(theregion
role)
The last two in this list require some footnotes.
-
<form role="search">
explicitly specifies the landmark role ofsearch
with therole
attribute, which would be redundant for the other 7 elements. -
<section>
has a role ofregion
only if it has an accessible name (MDN Contributors 2021a). 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), cited by Coyier (2013), 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) 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) 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).
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) 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) and by Lazaris (2020).
Counter-argument
But it seems that this practice is not widely accepted.
Akymenko (2019), 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), Gunnarsson (2020) 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) rather than Lazaris (2020), 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), 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", Accessibility Developer Guide, May 14, 2018 (last updated).
Akymenko, Maks (2019) "Hamburger Menu with a Side of React Hooks and Styled Components", CSS-Tricks, Sep 10, 2019.
Coyier, Chris (2013) "Using WAI-ARIA Landmarks", CSS-Tricks, Feb 18, 2013.
Devlin, Ian (2011) "It's completely up to you....", Stack Overflow, Feb 2, 2011.
Evans, Alicia (2020) "Let’s Focus on Slide-Out Navigation", Knowbility, Mar 26, 2020.
Faulkner, Steve (2013) "Using WAI-ARIA Landmarks – 2013", TPGi, Feb 12, 2013.
Gunnarsson, Birkir (2020) "This is looking very good. A couple of usability suggestions...", Impressive Webs, Jul 2, 2020.
Kudamatsu, Masa (2019) "Semantic HTML as graphic design without graphics", Web Dev Survey from Kyoto, Jul 11, 2019.
Lazaris, Louis (2020) "Accessible and Keyboard-Friendly Hamburger Menu + Slide Out Navigation", Impressive Webs, Jul 3, 2020.
MDN Contributors (2021a) ": The Generic Section element", MDN Web Docs, Jun 3 2021 (last updated).
MDN Contributors (2021b) "Document and website structure", MDN Web Docs, Jun 7, 2021 (last updated).
MDN Contributors (2021c) "Using ARIA: Roles, states, and properties", MDN Web Docs, Apr 19, 2021.
Pickering, Heydon (2017) "Menus & Menu Buttons", Inclusive Components, May 10, 2017.
Schwerdtfeger, Rich. (2013) "Probably the most important rule for applying landmarks is...", TPGi, Feb 12, 2013.
Silver, Adam (2019) "Why, How, and When to Use Semantic HTML and ARIA", CSS-Tricks, May 7, 2019.
Top comments (7)
I've never seen a well-written and properly structured article like this in dev.to
(reminds me of my college thesis with those citations and references, LOL)
Anyway, Great work!👏
This gave me a new insight in better structuring my markup, thanks a lot!
I am building my portfolio atm and this article was helpful and timely.
thank you.
great article, very complete and informative. thanks!
It’s interesting that all the examples on MDN in the context of discussing landmark roles have nav nested within header. I wonder whether the following from (Faulkner 2013, emphasis added) saves the accessibility of doing so?
Responding to my own comment, to call it into doubt. After a more careful reading of my quote from Faulkner: although it says that “informing the user that the item has sub items,” it does not say “informing the user that the item has subsidiary nested landmark items.” Thus, a reader may assume that the nav landmark container is in a subsequent top-level landmark container and therefore may not bother to delve further into the header.
Thank you for this article. My question now is, can this pattern be used for websites for which a hamburger menu button is not required. If so, how can the header, and nav elements be styled for a coherent visual?
Curious, has anyone installed a screen reader to compare the experience between the different layouts?