Skip to main content

Notes

Accessible Breadcrumb Navigation: The WAI-ARIA Pattern for E-Commerce Category Pages

Quietramp ·

Accessible Breadcrumb Navigation: The WAI-ARIA Pattern for E-Commerce Category Pages

Quick answer: A breadcrumb trail should be a real list of links (<ol> of <a> elements) wrapped in a <nav> landmark labeled with aria-label="Breadcrumb" (or aria-labelledby), with aria-current="page" on the link representing the current page. That’s the entire WAI-ARIA Authoring Practices Guide (APG) Breadcrumb pattern — no custom keyboard handling needed, since it’s built entirely from native links. A row of plain text separated by > characters, or a <div> with click handlers standing in for links, gives a screen reader no indication it’s a navigation trail at all.

This article covers technical accessibility practice, not legal advice — it explains what WCAG 2.1 AA requires for navigation components and how to implement it, not whether a specific site carries legal risk.

Where this shows up on an e-commerce site

Breadcrumbs are near-universal on category and product pages: “Home > Women > Shoes > Sneakers,” or a filtered path like “Home > Sale > Under $50.” They matter more in e-commerce than on a simple brochure site because catalog hierarchies are often three or four levels deep, and a shopper who lands on a product page from search or a shared link has no other on-page cue for how they got there or how to step back up one level. This is Quietramp’s own observation from reviewing e-commerce sites, not something the spec itself calls out — the APG defines the pattern, not where a store should use it.

The APG’s own definition is short and direct: “A breadcrumb trail consists of a list of links to the parent pages of the current page in hierarchical order. It helps users find their place within a website or web application.”

Why a plain-text or div-based breadcrumb fails

1. No structure or list semantics (fails SC 1.3.1 Info and Relationships)

WCAG SC 1.3.1 Info and Relationships (Level A) requires that “information, structure, and relationships conveyed through presentation can be programmatically determined or are available in text.” A sighted user reads “Home > Women > Shoes > Sneakers” as an ordered hierarchy purely from the > characters and left-to-right layout. Nothing about that is programmatically available unless the markup says so directly — a <span> full of text and literal > glyphs is, to a screen reader, one run of text. It doesn’t announce as a list, doesn’t convey that there are four items, and gives no signal about which one represents the page the user is currently on.

WCAG SC 4.1.2 Name, Role, Value (Level A) exists so that “for all user interface components… the name and role can be programmatically determined.” Some breadcrumb implementations style each level as a <span> or <div> with an onclick handler instead of a real <a href> — often to avoid default link underline/color styling rather than override it with CSS. A screen reader announces that element as plain text with no indication it’s interactive, and it typically isn’t in the keyboard Tab order at all, since only genuinely focusable elements (links, buttons, and anything given an explicit tabindex) are.

WCAG SC 2.4.4 Link Purpose (In Context) (Level A) requires that “the purpose of each link can be determined from the link text alone or from the link text together with its programmatically determined link context.” Long category names get visually truncated with an ellipsis to fit a narrow breadcrumb bar — “Women’s Athletic Footwear & Acce…” — and if the truncation is done by simply cutting the visible text rather than truncating only the display while keeping the full string as the link’s accessible name, a screen reader reads out the cut-off fragment as if it were the whole link.

The fix: the APG Breadcrumb pattern

Per the APG’s Roles, States, and Properties section, the pattern has three requirements:

  • “Breadcrumb trail is contained within a navigation landmark region.”
  • “The landmark region is labelled via aria-label or aria-labelledby.” — necessary because most pages already have a primary site-navigation <nav> (the main menu); without a label, assistive technology has no way to distinguish the two navigation regions from each other.
  • “The link to the current page has aria-current set to page. If the element representing the current page is not a link, aria-current is optional.”

The APG’s own worked example page shows exactly what that looks like in markup — notably, it keeps the current-page item as a link (with an empty href) rather than removing the link entirely:

<nav aria-label="Breadcrumb">
  <ol>
    <li><a href="/">Home</a></li>
    <li><a href="/women">Women</a></li>
    <li><a href="/women/shoes">Shoes</a></li>
    <li><a href="/women/shoes/sneakers" aria-current="page">Sneakers</a></li>
  </ol>
</nav>

Two details worth calling out for anyone implementing this from a copy-pasted example:

  • The <ol> matters, not just the links inside it. An ordered list is what gives a screen reader the “item 2 of 4” style announcement that conveys hierarchy — a <nav> wrapping bare <a> tags with no list at all restores the landmark and label but still loses the structural signal SC 1.3.1 is asking for.
  • The current page can stay a real link, or drop the link entirely — the spec allows either. The APG’s own text is explicit that aria-current is only required when the current-page element is a link; if a team instead renders the last breadcrumb item as plain text (a defensible choice, since linking to the page you’re already on serves no function), aria-current becomes optional rather than missing a requirement. What to avoid is the common middle ground: a href="#" dead link with no aria-current at all, which is both a non-functional link and an unmarked current-page indicator at once.

Handling the visual separators

The > or / characters between breadcrumb items are a CSS concern, not an ARIA one — the pattern itself says nothing about them, since the <li> boundaries already convey separation programmatically. The common, defensible approach: render separators with CSS (::before / ::after content, or a background image) rather than as literal characters inside the link text, so a screen reader reading each list item doesn’t announce a stray “greater than” between every level. If a separator does need to exist as an actual DOM character for styling reasons, mark it aria-hidden="true" so it’s skipped by assistive technology while remaining visible on screen.

What a scan catches, and what a person has to check

An automated scanner reliably flags a <div>-based breadcrumb with no link roles at all, and can often catch a missing aria-label on a <nav> landmark. What it generally can’t verify: whether aria-current="page" is actually applied to the correct item after a template is reused across different category depths (a common bug — a shared component defaults to marking the last static item rather than the true current page), whether truncated link text still carries its full string as the accessible name, and whether the breadcrumb reads in a sensible order when navigated by screen reader rather than just looking correct on screen. Confirming those needs a keyboard and a screen reader pass, not just a check that <nav> and <ol> tags exist somewhere in the markup.

FAQ

Does the breadcrumb <nav> need role="navigation"? No — <nav> carries the navigation landmark role implicitly in HTML. Adding role="navigation" on top of a native <nav> element is redundant, not required by the pattern.

What if my breadcrumb has just one or two levels — is it still worth doing this properly? Yes. The pattern doesn’t have a minimum-depth exception, and a two-level trail (“Home > Sneakers”) still benefits from the same landmark label and aria-current marking — the implementation cost is the same regardless of trail length.

Does a breadcrumb replace the need for a page <h1> or other heading structure? No. A breadcrumb tells a user where they are in the site hierarchy; it isn’t a substitute for a descriptive page title or heading, and WCAG’s heading-related criteria still apply to the page’s actual content independently.

Get your navigation checked by a person, not just a parser

Quietramp’s $890 audits include a manual pass through structural navigation components like breadcrumbs — checking landmark labeling, list semantics, and aria-current accuracy with an actual screen reader, not just confirming that a <nav> tag exists somewhere in the DOM. See a real sample report or check pricing.


This is educational content about technical accessibility practice, not legal advice. Meeting WCAG 2.1 AA does not constitute a legal compliance determination under the ADA or any other standard — consult qualified counsel for legal risk questions.

This article was drafted with AI assistance and reviewed by a person for accuracy before publication.

← Back to Notes