< nav >
The nav element: not every list of links
A sectioning element for major navigation links. The nav element is one of the most misapplied sectioning elements because the spec is narrower than most developers expect. Not every group of links is a nav. Used precisely, it produces a navigation landmark that assistive technology users can jump to directly, and it pairs with aria-current to give the "you are here" indicator the platform already ships.
Built-in with native HTML
- Automatic navigation landmark. A
<nav>element maps torole="navigation"without any ARIA. Screen reader users can jump to it through landmark navigation. - Multiple navs per page are allowed. A primary site nav, a footer nav, a breadcrumb, a table of contents, and a pagination control can all coexist as separate nav elements.
- Nesting is allowed. A table of contents nav inside an article is valid alongside a top-level primary nav.
- Works with real anchors. The links inside a nav are
<a href>anchors, which give middle-click, command-click, right-click "copy link," status-bar preview, and native inclusion in the browser's link list. - Pairs with
aria-currentto indicate the active link without any class-toggling script.
What <nav> actually means
The specification defines nav as a section that links to other pages or to parts within the page: a section with navigation links. The spec is explicit that not every group of links belongs in a nav:
Only sections that consist of major navigation blocks are appropriate for the nav element.
"Major" is the operative word. A paragraph of prose with three inline links is not a nav. A short list of legal links in the footer does not need a nav; the <footer> element alone is enough. A nav is for a navigation block that a reader might reasonably want to skip to, skip past, or return to.
A useful test: would a screen reader user benefit from being able to jump directly to this group of links as a distinct region of the page? If yes, it's a nav. If the links are incidental to the surrounding content, they aren't.
Why the distinction matters: landmarks
Every <nav> produces a navigation landmark. Landmarks are how assistive technology users move through a page at the structural level, the same way sighted users scan for visual anchors.
Marking every list of links as a nav dilutes this. A page with seven nav elements presents seven navigation landmarks, and the list stops being useful. A page with two or three well-chosen navs, each named, presents a clean structural map.
When a page has more than one nav, each one needs an accessible name so landmark lists can distinguish them.
Accessible naming
A nav with a visible heading uses aria-labelledby:
<nav aria-labelledby="primary-nav-heading">
<h2 id="primary-nav-heading" class="visually-hidden">Primary</h2>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/elements/">Elements</a></li>
<li><a href="/about/">About</a></li>
</ul>
</nav>
A nav without a visible heading uses aria-label:
<nav aria-label="Breadcrumb">
<ol>
<li><a href="/">Home</a></li>
<li><a href="/elements/">Elements</a></li>
<li><a href="/elements/nav/" aria-current="page">nav</a></li>
</ol>
</nav>
Two conventions worth keeping:
- Don't include the word "navigation" in the label. The landmark role already announces that.
aria-label="Primary navigation"is typically read as "Primary navigation, navigation." - Name every nav when there are two or more. A single nav on a page is unambiguous and does not strictly need a label, though one does no harm.
aria-current: the platform's "you are here" indicator
The active link in a nav is the most common place to reach for a JavaScript-driven class toggle. The platform has a dedicated attribute for this.
<nav aria-label="Primary">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/elements/" aria-current="page">Elements</a></li>
<li><a href="/about/">About</a></li>
</ul>
</nav>
Valid values for aria-current:
pagefor the current page in a set of navigational links.stepfor the current step in a multi-step process.locationfor the current location in a breadcrumb or similar.dateandtimefor the current date or time in a list.truefor a generic current item when none of the above fits.false(the default).
Browsers expose [aria-current] as a CSS attribute selector, so the visual "active" styling can hang off the attribute directly:
nav a[aria-current="page"] {
font-weight: 600;
color: CanvasText;
}
One attribute, one CSS rule, one accessible announcement, zero JavaScript state.
Composite patterns where <nav> is the right element
- Primary site navigation, typically inside
<header>, containing the top-level links for the site. - Breadcrumbs, a
<nav aria-label="Breadcrumb">wrapping an<ol>of anchors, witharia-current="page"on the final item. - Pagination, a
<nav aria-label="Pagination">wrapping prev/next and page-number links. Use real anchors with real hrefs so the browser's built-in link handling applies. - Table of contents, a
<nav aria-label="Contents">usually nested inside the<article>it describes, with in-page anchors (href="#section-id"). - Footer site map, the expanded multi-column link grid in a large site's footer. Each column can be its own nav, named by its column heading.
- Sidebar section nav, the per-section navigation in a documentation site, distinct from the primary nav.
- Skip links, the "skip to main content" anchor at the top of the document. A single skip link does not require a nav wrapper; the anchor itself is sufficient. A group of skip links (skip to main, skip to search, skip to footer) can be wrapped in
<nav aria-label="Skip links">.
What <nav> is not
- Not every list of links. A sentence with inline links is prose. A short legal line in the footer is a footer.
- Not decorative link groups. A row of social media icons at the bottom of the page is not a major navigation block.
- Not a table of tangential links inside an article. That's an
<aside>. A table of contents is a nav; a "related reading" box is an aside. - Not a menu of in-page actions. A menu of buttons that perform actions, rather than navigate, is a toolbar (
role="toolbar") or a menu (role="menu"), not a nav. - Not a wrapper for a single primary link. A "back to home" anchor on its own is an anchor.
A useful test: if the group of links were removed, would a reader lose a way to move through the site or the document? If yes, it's a nav. If the page's structure still makes sense without them, they probably belong in whatever surrounding element they sit inside.
Already HTML-available
Patterns that HTML handles natively, which are often rebuilt in JavaScript:
role="navigation"on a<div>. The native<nav>element already carries the navigation role. A div with an ARIA role is the element plus an attribute, with no advantage over the element itself.- Custom link components that don't render real anchors. A clickable element without an
hrefloses middle-click, command-click, right-click context menu, status-bar URL preview, and inclusion in the browser's and screen reader's link lists. Client-side routers can intercept anchor clicks withevent.preventDefault()without giving up any of this, and most do. - Class-toggled "active" link state. The
aria-current="page"attribute announces the active link to assistive technology and is selectable in CSS with[aria-current="page"]. No state-tracking script is required to style the active link. - Custom breadcrumb widgets. A
<nav aria-label="Breadcrumb">wrapping an ordered list of anchors, witharia-current="page"on the last item, is the WAI-ARIA APG breadcrumb pattern in full. - Custom pagination widgets. A
<nav aria-label="Pagination">wrapping a list of page-number anchors, witharia-current="page"on the active page andrel="prev"andrel="next"on the prev/next controls, gives browsers and assistive tech everything they need. - Hand-built dropdown menus wired up with click handlers and
aria-expanded. The disclosure-style dropdown (a button revealing a group of links) can start from<details>and<summary>, or from a<button popovertarget>paired with a[popover]region, with focus return and top-layer rendering handled by the browser. - Custom "skip to main" widgets. A styled anchor with
href="#main"and focus-visible styling is the skip link. No component is needed.
Invoker commands (command and commandfor) and the broader popover API are the newer of these. Current browser support is worth verifying before relying on them in production.
Reference:
- WHATWG
- the-nav-element
- caniuse.com
- mdn-html_elements_nav
- MDN Docs
- Web/HTML/Element/nav
- WAI-ARIA APG
- Landmark Regions
- Breadcrumb Pattern
- ARIA
- aria-current