Navigation Structures

Learn to build accessible, semantically correct navigation menus and breadcrumb trails using the <nav> element, and how to mark the current page for both sighted and assistive-technology users.

Almost every website has some form of navigation — a menu at the top linking to major sections, a sidebar of related pages, or a breadcrumb trail showing where the current page sits within the site's structure. HTML provides a dedicated <nav> element specifically for grouping these navigation links, distinct from ordinary lists of links elsewhere on a page. This lesson covers how to build menus and breadcrumbs with <nav>, why using <nav> (rather than a generic <div>) matters for accessibility, how to label multiple navigation regions on the same page, and how to indicate which link represents the page the user is currently on.

The <nav> Element as a Landmark

The <nav> element identifies a block of navigation links — major site-wide navigation, a sidebar of related links, or a table of contents for a long article. It's one of HTML's 'landmark' elements (alongside others like <header>, <main>, and <footer>) that assistive technology uses to let users jump directly to important regions of the page, skipping past everything else.

Not every group of links on a page needs to be wrapped in <nav>. A handful of links scattered within an article's body text, or a small list of 'related products' at the bottom of a shopping page, don't necessarily need it. <nav> is meant for major, reusable navigation blocks — the kind of link groups a user would specifically want to locate and jump to.

Building a Menu

A typical navigation menu is built by wrapping a list of links — usually an unordered list, <ul>, containing <li> items each holding an <a> — inside a <nav> element. Using a list (rather than just a series of bare links) gives the menu additional semantic structure: assistive technology can announce how many items the menu contains and let users navigate list item by list item.

Internal page navigation — a 'jump to section' menu that uses fragment links (covered in the previous lesson) to scroll to different headings on the same long page — is also commonly wrapped in its own <nav>, especially for long documentation pages or articles with a table of contents.

Breadcrumbs

A breadcrumb trail shows a user's current location within a site's hierarchy, typically as a chain of links separated by a delimiter like '>' — for example: Home > Electronics > Laptops > Gaming Laptops. Breadcrumbs help users understand where they are and let them jump back up to any parent level in one click, without needing to use the browser's back button repeatedly.

Breadcrumbs are conventionally marked up as an ordered list (<ol>) inside a <nav>, since the sequence of the trail matters — each step represents a level deeper in the hierarchy. The final item, representing the current page, is typically not a link at all (since linking to the page you're already on serves no purpose), or if it is included as a link for consistency, it's marked with aria-current="page" (covered below) rather than being treated as a normal clickable destination.

Accessible Navigation: Labeling Multiple <nav> Elements

It's common for a page to contain more than one <nav> element — for instance, a main site menu near the top and a separate 'in this article' table of contents further down, or a footer navigation block. When a screen reader user pulls up a list of landmarks on the page, multiple unlabeled <nav> regions all just announce as 'navigation,' giving no way to tell them apart.

The fix is to add an aria-label attribute to each <nav>, giving it a short, descriptive name — for example, aria-label="Main navigation" and aria-label="Table of contents". This does not affect the visible page at all; it exists purely to give assistive technology a meaningful name for each landmark, so screen reader users can quickly choose the right one from a list like 'navigation: Main navigation' and 'navigation: Table of contents.'

Marking the Active Page with aria-current

When a navigation menu contains a link to the very page the user is currently viewing, it's good practice to visually distinguish that link (commonly with a different color, bold text, or an underline via CSS) so the user can immediately see where they are in the site. But visual styling alone doesn't communicate that information to screen reader users.

The aria-current attribute solves this. Setting aria-current="page" on the link that represents the current page tells assistive technology that this specific link represents the page currently being viewed, distinct from the other links in the same menu. Screen readers can then announce it as, for example, 'Products, current page' — clearly communicating the same information sighted users get from the visual styling.

A common pattern combines both: the link gets aria-current="page" for accessibility, and a CSS selector targeting [aria-current="page"] applies the visual highlight — meaning a single attribute drives both the accessible announcement and the visual indicator, keeping them reliably in sync.

Navigation Markup Syntax

aria-label gives an unlabeled landmark a distinguishing name, useful when a page has more than one <nav>. aria-current="page" marks the link (or item) representing the page currently being viewed.

<nav aria-label="Main navigation">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/products.html" aria-current="page">Products</a></li>
    <li><a href="/contact.html">Contact</a></li>
  </ul>
</nav>

<nav aria-label="Breadcrumb">
  <ol>
    <li><a href="/">Home</a></li>
    <li><a href="/electronics.html">Electronics</a></li>
    <li aria-current="page">Laptops</li>
  </ol>
</nav>

Code Examples

A minimal navigation menu — three links wrapped in a <nav> element, without a list structure. Expected result: Three clickable links displayed next to each other (or stacked, depending on default/CSS styling), identified as a navigation landmark by assistive technology.

A more structured menu using an unordered list inside <nav>, with an aria-label naming this particular navigation region 'Main navigation'.

Wrapping the links in <ul><li> gives screen readers extra structure, such as announcing 'list of 3 items' when entering the menu.

A breadcrumb trail built as an ordered list (since sequence/depth matters) inside a labeled <nav>. Every step except the current page is a clickable link; the final step, representing the page the user is already on, is plain text marked with aria-current="page" rather than a link. Using <ol> instead of <ul> for breadcrumbs isn't strictly required by browsers, but it's the more semantically accurate choice since breadcrumb order encodes real hierarchy depth.

The last <li> intentionally has no <a> inside it — linking to the current page would be a link to nowhere useful, so it's left as plain text but still marked as the current location via aria-current.

A realistic page with two distinct <nav> regions — a site-wide main menu (with the Home link marked as the current page) and a separate in-page table of contents using fragment links — each given a distinguishing aria-label so screen reader users can tell them apart when browsing the page's landmarks.

Common mistake: Leaving both <nav> elements without aria-label would cause a screen reader's landmark list to show two entries that both simply say 'navigation,' forcing the user to open each one just to figure out which is which.

<nav>
  <a href="/">Home</a>
  <a href="/about.html">About</a>
  <a href="/contact.html">Contact</a>
</nav>
<nav aria-label="Main navigation">
  <ul>
    <li><a href="/">Home</a></li>
    <li><a href="/shop.html">Shop</a></li>
    <li><a href="/about.html">About</a></li>
  </ul>
</nav>
<nav aria-label="Breadcrumb">
  <ol>
    <li><a href="/">Home</a></li>
    <li><a href="/electronics.html">Electronics</a></li>
    <li><a href="/electronics/laptops.html">Laptops</a></li>
    <li aria-current="page">Gaming Laptops</li>
  </ol>
</nav>
<header>
  <nav aria-label="Main navigation">
    <ul>
      <li><a href="/" aria-current="page">Home</a></li>
      <li><a href="/courses.html">Courses</a></li>
      <li><a href="/pricing.html">Pricing</a></li>
    </ul>
  </nav>
</header>

<nav aria-label="Table of contents">
  <ul>
    <li><a href="#introduction">Introduction</a></li>
    <li><a href="#getting-started">Getting Started</a></li>
    <li><a href="#advanced-topics">Advanced Topics</a></li>
  </ul>
</nav>

A Page With Multiple Labeled Navigation Regions

Without aria-label, all three would announce only as 'navigation,' indistinguishable from one another.

<header>
  <nav aria-label="Main navigation">  ---- site-wide menu
</header>
<main>
  <nav aria-label="Table of contents">  ---- jump within article
  <article>...</article>
</main>
<footer>
  <nav aria-label="Footer links">  ---- legal / secondary links
</footer>

Screen reader's landmark list now shows:
  navigation: Main navigation
  navigation: Table of contents
  navigation: Footer links

Important Rules

Wrap major, reusable link groups — site menus, tables of contents, breadcrumbs — in <nav>, not every small cluster of links on a page.

Add aria-label to each <nav> element when a page has more than one, so assistive technology can distinguish them.

Mark the link (or item) representing the currently viewed page with aria-current="page".

Don't link the final breadcrumb item to itself — leave it as plain text marking the current location.

Use lists (<ul> for menus, <ol> for breadcrumbs) inside <nav> to give the link group additional structure.

Breadcrumbs and Search Engines

Search engines like Google can parse well-structured breadcrumb navigation and display it directly in search results below the page title, showing users the site hierarchy (e.g., 'example.com > Electronics > Laptops') before they even click through. This is one more practical reason to mark up breadcrumbs semantically and consistently, rather than as plain unstructured text separated by '>' characters with no underlying link structure.

<nav>...</nav> <!-- further down the page --> <nav>...</nav>

<nav aria-label="Main navigation">...</nav> <!-- further down the page --> <nav aria-label="Table of contents">...</nav>

Two unlabeled <nav> elements both announce simply as 'navigation' to assistive technology, giving screen reader users no way to distinguish the site's main menu from an in-page table of contents.

<li><a href="/electronics/laptops.html">Laptops</a></li> <!-- current page --> <li aria-current="page">Laptops</li>

Linking the final breadcrumb item to the page the user is already viewing serves no purpose and doesn't communicate 'you are here' to screen reader users the way aria-current="page" does.

[True / False] True or False: If a page has only one <nav> element, adding aria-label to it is still strictly required for the page to be considered accessible. A. True — every <nav> element must always have an aria-label regardless of how many are on the page B. False — aria-label is primarily needed to distinguish multiple <nav> regions from one another; a single, unambiguous <nav> is not required to have one, though a descriptive label is never harmful

B. False — aria-label is primarily needed to distinguish multiple <nav> regions from one another; a single, unambiguous <nav> is not required to have one, though a descriptive label is never harmful — aria-label on <nav> exists mainly to help users tell apart multiple navigation landmarks on the same page. With only one <nav>, a screen reader's landmark list already has nothing to confuse it with, so labeling it is a nice-to-have rather than a strict requirement — though it's still good practice and never hurts.

Build a two-level breadcrumb trail for a page titled 'Wireless Mice' that sits under a 'Computer Accessories' category, itself under 'Home'. Mark the current page correctly and label the <nav>.

<nav aria-label="Breadcrumb"> <ol> <li><a href="/">Home</a></li> <li><a href="/accessories.html">Computer Accessories</a></li> <li aria-current="page">Wireless Mice</li> </ol> </nav>

Use an <ol> inside a <nav aria-label="Breadcrumb">, with the final item unlinked and marked aria-current="page".