-
-
Notifications
You must be signed in to change notification settings - Fork 555
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
How to: Article how to make an accessible nav with dropdowns #1472
Open
jimbateson
wants to merge
13
commits into
a11yproject:main
Choose a base branch
from
jimbateson:Article-HOW-TO-make-an-accessible-nav-with-dropdowns
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
a2e1faf
feat: first draft of the accessible nav how to article
jimbateson7 42ae52d
fix: first pass and fix of SPAG
jimbateson7 2fc387f
chore: date change and nav syntax consistency
jimbateson7 bf169ff
fix: changes from Anya proof
jimbateson7 4be5041
fix: changes from Hemingway first run
jimbateson7 6e27a42
chore: final proof edits
jimbateson7 2c7f44c
fix: caught a couple of last min SPAG bits
jimbateson7 ee903f8
chore: added short explanation and further links to define assitive t…
jimbateson7 5ccade9
fix: first round of changes.
jamesbatesoncode aced8ff
fix: added aria(-current) styling hook explanation
jamesbatesoncode 3b94ee3
fix: switched order of showing/hiding the dropdown tip
jamesbatesoncode 404459b
feat: first go at adding a little summary
jamesbatesoncode f2314eb
fix: removed support note from nav initial explanation
jamesbatesoncode File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
--- | ||
title: Make an accessible <nav> with dropdowns | ||
title: Make an accessible <code><nav></code> with dropdowns | ||
description: Navigation is a critical part of any application, it allows people to complete journeys and find the information they need. So making it accessible is key. | ||
category: How-to | ||
author: James Bateson | ||
|
@@ -11,37 +11,19 @@ further_reading: | |
- title: "Don't use ARIA menu roles for site nav" | ||
url: https://adrianroselli.com/2017/10/dont-use-aria-menu-roles-for-site-nav.html | ||
source: Adrian Roselli | ||
- title: "Navigation role support" | ||
url: https://a11ysupport.io/tech/aria/navigation_role | ||
source: Accessibility Support | ||
- title: "Top 5 rules of ARIA" | ||
url: https://www.deque.com/blog/top-5-rules-of-aria/ | ||
source: Deque | ||
- title: "Are your anchor links accessible?" | ||
url: https://amberwilson.co.uk/blog/are-your-anchor-links-accessible/ | ||
source: Amber Wilson | ||
- title: "Local Navigation Is a Valuable Orientation and Wayfinding Aid" | ||
url: https://www.nngroup.com/articles/local-navigation/ | ||
source: Nielsen Norman Group | ||
- title: "Cognitive accessibility" | ||
url: https://developer.mozilla.org/en-US/docs/Web/Accessibility/Cognitive_accessibility | ||
source: MDN Web Docs | ||
- title: "Fable assisitve technology glossary" | ||
url: https://makeitfable.com/glossary/ | ||
source: Fable | ||
thanks: "Anya Mueller, Alex Hall" | ||
tags: | ||
- howto | ||
--- | ||
|
||
Navigation is a critical part of any application and can often involve many levels of nesting. It allows people to complete journeys and find the information they need. So making it accessible is key. HTML5 includes the <nav> section element to help with this. | ||
Navigation is a critical part of any application and can often involve many levels of nesting. It allows people to complete journeys and find the information they need. So making it accessible is key. HTML includes the <code><nav></code> landmark element to help with this. | ||
|
||
## The nav section element | ||
## The <code><nav></code> landmark element | ||
|
||
Let's start with a quick overview of <nav>. The <nav> section element has semantic meaning and comes with accessibility benefits by using it to mark-up sections of navigation. | ||
Let's start with a quick overview of <code><nav></code>. The <code><nav></code> landmark element has semantic meaning and comes with accessibility benefits by using it to mark-up sections of navigation. | ||
|
||
<blockquote> | ||
<p>The <nav> HTML element represents a section of a page whose purpose is to provide navigation links, either within the current document or to other documents. Common examples of navigation sections are menus, tables of contents, and indexes.</p> | ||
<p>The <code><nav></code> HTML element represents a section of a page whose purpose is to provide navigation links, either within the current document or to other documents. Common examples of navigation sections are menus, tables of contents, and indexes.</p> | ||
<footer> | ||
<cite><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/nav">MDN web docs: <nav>: The Navigation Section element</a></cite> | ||
</footer> | ||
|
@@ -62,26 +44,30 @@ Here's the example markup that we'll build up throughout this article. It's wort | |
|
||
### Semantics | ||
|
||
The <nav> element will communicate a role of navigation-equal to setting `role="navigation"`, (this may still need to be added if needing to [support some assistive technology](https://a11ysupport.io/tech/aria/navigation_role)) meaning it can be easily navigated to by people with screen readers—as a landmark. | ||
The <code><nav></code> element will communicate a role of navigation-equal to setting `role="navigation"`, (this may still need to be added if needing to [support some assistive technology](https://a11ysupport.io/tech/aria/navigation_role)) meaning it can be easily navigated to by people with screen readers—as a landmark. | ||
|
||
**Note**: Assistive technologies are systems and services that can provide people with independance and help remove exlusions and the inability participate in society. For some examples [Fable has a glossay](https://makeitfable.com/glossary/) of terms and services and there is a [section of this site dedicated to articles related to assitive technology](https://www.a11yproject.com/posts/#assistive-technology). | ||
### Best practice | ||
|
||
### Best practices summarized | ||
- Not all blocks containing links need to use <code><nav></code>. Use it for larger sections of navigation links. Overuse can create "noise" for people using screen readers. | ||
- Uniquely label the <code><nav></code> to give a better idea of its purpose. This can be done with a heading or `aria-label` or `aria-labelledby`. **Note**: Screen readers will already announce the element as being navigation, so avoid using the word "nav" or "navigation" in the accessible name. | ||
- For site navigation with more than two links, consider using a list (`<ul>` or `<ol>`) inside of the <code><nav></code>. This will allow people who use assistive technology to know how many links the list contains. | ||
|
||
- Not all blocks containing links need to use <nav>. Use it for larger sections of navigation links. Overuse can create 'noise' for people using screen readers. | ||
- Uniquely label the <nav> to give a better idea of its purpose. This can be done with a heading or `aria-label`/`aria-labelledby`. **Note**: Screen readers will already announce the element as being navigation, so avoid using the word 'nav' or 'navigation' in the accessible name. | ||
- For site navigation consider using a list (`<ul>/<ol>`) inside of the <nav>. So that assistive technology can announce how many links it contains. | ||
#### Using a heading & aria-labelledby | ||
|
||
```html | ||
<nav aria-labelledby="main-nav-label"> | ||
<h2 id="main-nav-label" class="visually-hidden">Main menu</h2> | ||
<h2 id="main-nav-label" class="visually-hidden">Main</h2> | ||
|
||
<ul> | ||
... | ||
</ul> | ||
</nav> | ||
``` | ||
|
||
#### Using an aria-label | ||
|
||
<nav aria-label="Main menu"> | ||
```html | ||
<nav aria-label="Main"> | ||
<ul> | ||
... | ||
</ul> | ||
|
@@ -90,7 +76,7 @@ The <nav> element will communicate a role of navigation-equal to setting ` | |
|
||
## Adding dropdowns | ||
|
||
Navigation designs often need many levels of links underneath a top-level link. This results in using the dropdown pattern, whereby a hidden set of links are shown by interacting with the parent, this can be many levels deep. Some accessibility considerations must be made before implementation. | ||
Navigation often needs one or more levels of links underneath a top-level link. This results in using the dropdown pattern, whereby a hidden set of links are shown by interacting with the parent. This approach can nest links many levels deep. | ||
|
||
- How would the navigation show if there were no styles? | ||
- How should the parent link toggle the dropdown? | ||
|
@@ -101,7 +87,7 @@ Navigation designs often need many levels of links underneath a top-level link. | |
Dropdown sub-navigation is typically marked up as a nested list inside of the parent link list item. | ||
|
||
```html | ||
<nav aria-label="Main menu"> | ||
<nav aria-label="Main"> | ||
<ul> | ||
<li><a href="#">Home</a></li> | ||
<li> | ||
|
@@ -123,21 +109,27 @@ Structuring the markup as shown in the previous example means without any CSS lo | |
|
||
### Tip 2: Parent link toggle | ||
|
||
Navigation patterns will often attach a click/focus event to the entire parent link to reveal the dropdown of nested items. This comes with two problems. Using a click means extra functionality is needed to handle the primary purpose of the parent link, which should itself act as a link. By using focus, people traversing the navigation using a keyboard would be required to tab through all dropdowns regardless of whether they wanted to or not. | ||
Navigation patterns will often attach a click/focus event to the entire parent link to reveal the dropdown of nested items. This comes with two problems: | ||
|
||
1. Using a click means extra functionality is needed to handle the primary purpose of the parent link, which should itself act as a link. | ||
2. By using focus, people traversing the navigation using a keyboard would be required to tab through all dropdowns regardless of whether they wanted to or not. | ||
|
||
Adding a toggle element, for example, an arrow icon button, within the parent link allows people to only show the dropdown if they are interested in seeing further links associated with the parent. Make sure that the toggle element has enough of a tap/click (this pattern could be used for mobile as well) area and accessible focus/hover states. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could we link to an example of what a toggle element is? This is the first time we've mentioned it, but it is vital for constructing accessible tiered nav. |
||
|
||
**Note:** If your parent elements don't need to be a link themselves, make sure to use a `<button>` element, so that they can communicate they are expandable and have an event associated and benefit from all the accessible goodness buttons get for free. | ||
**Note:** If your parent elements don't need to be a link themselves, make sure to use `<button type="button">` element, so that they can communicate they are expandable and have an event associated and benefit from all the accessible goodness buttons get for free. | ||
|
||
```html | ||
<nav aria-label="Main menu"> | ||
<nav aria-label="Main"> | ||
<ul> | ||
<li><a href="#">Home</a></li> | ||
<li> | ||
<a href="#"> | ||
About Us | ||
<button> | ||
<svg aria-hidden="true">...</svg> | ||
<button type="button"> | ||
<!-- Visual cue icon - for example a downward facing chevron --> | ||
<svg aria-hidden="true" focusable="false"> | ||
<!-- Icon SVG code --> | ||
</svg> | ||
<span class="visually-hidden">Toggle About Us submenu</span> | ||
</button> | ||
</a> | ||
|
@@ -154,20 +146,22 @@ Adding a toggle element, for example, an arrow icon button, within the parent li | |
|
||
### Tip 3: Focus order | ||
|
||
By nesting the dropdown list as a direct child of the parent list item, it means that when visible, the first link will be the next focusable element after the parent item toggle. So adding a trigger inside the parent link is a great way to ensure a person intends to see the dropdown for that link and so take focus to the first link in said dropdown. | ||
By nesting the dropdown list as a direct child of the parent list item, it means that when visible, the first link will be the next focusable element after the parent item toggle. | ||
|
||
So adding a trigger inside the parent link is a great way to ensure a person intends to see the dropdown for that link and so take focus to the first link in said dropdown. | ||
|
||
Related to focus, another nice feature would be to make sure that if the person pressed the <kbd>ESC</kbd> key, the dropdown would close, and the person's focus return to the toggle element they used to open it. | ||
Related to focus, another nice feature would be to make sure that if the person pressed the <kbd>ESC</kbd> key, the dropdown would close, and the person's focus returns to the toggle element they used to open it. | ||
|
||
### Tip 4: Parent link functionality | ||
|
||
A parent link for a dropdown generally will still need to keep its functionality as a link. This can present problems if, for example, a click event has been attached to it to reveal a dropdown. Giving people an explicit way to toggle the visibility of dropdowns is a much nicer option. | ||
A parent link for a dropdown generally will still need to keep its functionality as a link. This can present problems, for example, a click event has been attached to it to reveal a dropdown. Giving people an explicit way to toggle the visibility of dropdowns via a separate control is a more accessible option. | ||
|
||
### Tip 5: Showing/hiding the dropdown | ||
|
||
When the navigation dropdown is closed, it's important to ensure the nested links are not visible to assistive technology. For example, people using a keyboard cannot tab to the links—this can lead to confusion on where their focus is on the page. | ||
|
||
To hide elements such as sub-menus from assistive technology, you should not rely on `opacity`. Although visually hidden, it would still allow the dropdown to be discoverable via assistive technology. To ensure that dropdowns are hidden until people choose to access that sub-navigation, consider toggling the `display: none;` or `visibility: hidden;` properties. | ||
jimbateson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
When the navigation dropdown is closed, it's important to ensure the nested links are not visible to assistive technology. For example, people using a keyboard cannot tab to the links—this can lead to confusion on where their focus is on the page. | ||
|
||
## What about ARIA? | ||
|
||
<blockquote> | ||
|
@@ -177,23 +171,26 @@ To hide elements such as sub-menus from assistive technology, you should not rel | |
</footer> | ||
</blockquote> | ||
|
||
When thinking about making some component interactions accessible, it's often assumed that more complex ARIA attributes and patterns may be needed. But a <nav> with dropdowns does not need any. There are [menu-related ARIA patterns available](https://www.w3.org/TR/wai-aria-practices/#menu). But these are slightly different in context from the site navigation pattern in this article. Menu ARIA is more designed to deal with native operating system-like menus, for example, a selection of options for a person. | ||
When thinking about making some component interactions accessible, it's often assumed that more complex ARIA attributes and patterns may be needed. But a <code><nav></code> with dropdowns <strong>does not</strong> need any. | ||
|
||
Although <nav> can be used without ARIA to create accessible navigation, there are things we can do with it to provide a better experience for people. | ||
Although <code><nav></code> can be used without ARIA to create accessible navigation, there are things we can do with it to provide a better experience for people: | ||
|
||
### Expanded states (aria-expanded) | ||
|
||
The `aria-expanded` attribute can be used to communicate whether a toggle control is expanded or collapsed. In our navigation example, this could be useful to inform people using screen readers if the dropdown is open or not, based on whether the toggle is expanded or collapsed. This value of the attribute would need to be changed via JavaScript when the person opened and closed the dropdown. | ||
|
||
```html | ||
<nav aria-label="Main menu"> | ||
<nav aria-label="Main"> | ||
<ul> | ||
<li><a href="#">Home</a></li> | ||
<li> | ||
<a href="#"> | ||
About Us | ||
<button aria-expanded="false"> | ||
<svg aria-hidden="true">...</svg> | ||
<!-- Visual cue icon - for example a downward facing chevron --> | ||
<svg aria-hidden="true" focusable="false"> | ||
<!-- Icon SVG code --> | ||
</svg> | ||
<span class="visually-hidden">Toggle About Us submenu</span> | ||
</button> | ||
</a> | ||
|
@@ -214,11 +211,11 @@ A common navigation design will see the currently active page link visually diff | |
|
||
## Skip links | ||
|
||
Although not technically required to make accessible navigation, making sure your site has a 'skip link' (usually visually hidden until tabbed to) that can bypass the main site navigation is a handy usability feature. It allows someone to jump directly to a page's <main> landmark, skipping common and repeated site areas, such as the navigation so the person does not need to traverse this content on every page. | ||
Although not technically required to make accessible navigation, making sure your site has a [skip link](https://www.a11yproject.com/posts/skip-nav-links/) that can be set to bypass the main site navigation is a handy usability feature. It allows someone to skip repeated site areas, such as the main navigation, so someone using assistive technology does not need to traverse this repetitive content on every page. | ||
|
||
## Alternatives | ||
|
||
Multi-level navigation with dropdowns often referred to as 'mega menus' can often be complex and need some thought to navigate. In certain cases, we might want to consider an alternative. | ||
Multi-level navigation with dropdowns often referred to as 'mega menus' can often be complex and need some thought to navigate. In certain cases, we might want to consider an alternative: | ||
|
||
### In-page navigation/table of contents | ||
|
||
|
@@ -236,3 +233,5 @@ Local navigation can help people understand where they are, and what content mig | |
</blockquote> | ||
|
||
**Note**: Be wary of changing how navigation appears and functions across multiple pages, predictability can be an important part of [cognitive accessibility](https://developer.mozilla.org/en-US/docs/Web/Accessibility/Cognitive_accessibility). | ||
jimbateson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
## Summary |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you don't need the parenthetical here.