Search topics
Breadcrumbs that mark the current page only by its look
A shop's breadcrumb trail is a row of loose links in a div, and its last crumb is grey by a class only, so a screen reader can't tell that it is a trail or which crumb is the page you are on.
<a href="/kitchen/mugs" class="current">Mugs</a> The problem
Screen reader users can't tell where the breadcrumb trail starts and ends, or which crumb is the page they are on, because only the layout and a grey colour show it.
A shop's category page for mugs opens with a breadcrumb trail: Home / Kitchen / Mugs. The design is tidy and familiar. Home and Kitchen are blue underlined links, and Mugs, the page you are on, is grey with no underline, so a sighted shopper who arrives from a search engine sees at once that they are in Mugs, under Kitchen, and can go up a level with one click.
A screen reader user pressing Tab through the same page hears "Home, link", "Kitchen, link", "Mugs, link". Nothing says that Mugs is the page they are on, or that the three links are a trail at all. Reading line by line, the slashes between the crumbs can be read out too. The trail is not announced as navigation and doesn't appear in the screen reader's list of landmarks, so it can't be found by jumping to it; it is only three more links among the header's.
The trail shows relationships: its links are a set for moving around the site, they run in order from the home page down to this one, and the last of them is the page being shown. WCAG 1.3.1 Info and Relationships requires information shown by presentation to be available in the code, or in the text. Here the grouping is only in the layout, because the trail is a div, which groups nothing for assistive technology; technique H97 meets 1.3.1 by putting related links in a nav. The order is only in the line of text, with no list to say how many crumbs there are. And the current page is only in the look: the current class turns Mugs grey and means nothing to the browser.
Breadcrumbs sit on nearly every shop category, product page, help centre and documentation site, and they usually come from one shared component, so one fix reaches every page. They matter most on pages people reach from a search engine or a shared link, where the trail is the quickest way to find out where they have landed, and on large sites with several levels.
1 of 10 groups affected
- No vision (affected)
- Low vision (not affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (not affected)
- Reach, strength (not affected)
- Cognitive (not affected)
- Seizures (not affected)
- Without vision A screen reader reads the crumbs as loose links, so the person can't tell that they are a trail or which one is the page they are on, and can't jump to the trail from the landmarks list. Someone who lands on the page from a search engine loses the quickest way to find out where they are.
A scanner finds three links with names and passes them. It can't tell that one is drawn as current, because a class called current or active means nothing to it, and it can't tell that a row of links in a div is a trail. EaseWeb's audit reports a crumb that links to the page being shown, in a trail named so by its class or name, that is drawn unlike the crumbs beside it and has neither aria-current nor text saying it is current. A trail outside any navigation landmark goes to a person as a review lead, with its links. AI code generators don't reliably fill the gap: Aaron Gustafson's tests of GPT-4, published in 2025, found it writing breadcrumb trails with no name on the nav and no aria-current="page". Listening to the trail on two pages is the only way to confirm it says where you are.
Try it
Press Tab to move through the trail, and Enter to go to another page.
The panel reads the top of the page as a screen reader does. Can you tell which crumb is the page you are on? Go deeper through the links under the heading, and back up through the trail.
Broken Can you fix this?
Reading from the top, a screen reader says:
- Home, link
- slash
- Kitchen, link
- slash
- Mugs, link
- Mugs, heading
The fix
Put the trail in a named nav, and say the current page in code, or leave it out of the trail.
- 1Put the breadcrumb trail in a
navwith its own short name, as an ordered list. - 2Mark the last crumb with
aria-current="page"and draw its look from it, or end the trail at the section above. - 3Draw the separators in CSS without text, or hide them, so they are never read.
<div class="breadcrumbs"> <a href="/">Home</a> <span class="sep">/</span> <a href="/kitchen">Kitchen</a> <span class="sep">/</span> <a href="/kitchen/mugs" class="current">Mugs</a></div><h1>Mugs</h1>A named nav, a list and aria-current
<nav class="breadcrumbs" aria-label="Breadcrumb"> <ol> <li> <a href="/">Home</a> </li> <li> <a href="/kitchen">Kitchen</a> </li> <li> <a href="/kitchen/mugs" aria-current="page">Mugs</a> </li> </ol></nav><h1>Mugs</h1>Why this fix: Style from the state, not a class
The current class gives Mugs its look and nothing else, and the div groups nothing. A screen reader reads "Home, link", "Kitchen, link", "Mugs, link", with the slashes between them at some punctuation settings.
The design is unchanged: every crumb looks as it was drawn. The trail is now a nav with its own name, so a screen reader announces "Breadcrumb, navigation" on the way in and lists it among its landmarks, and an ordered list, read as "list, 3 items" from the top down. aria-current="page" on Mugs makes screen readers say "current page" there, and the grey now selects on the attribute, so the look and the code can't mark different crumbs. The separator is a thin rotated line drawn by a border, with no text for a screen reader to read.
Both pass 1.3.1. Keep the last crumb, with aria-current="page", when the design shows it, or when the heading under the trail is far away or worded differently from the crumb: the design stays as drawn, and the look comes from the attribute. End the trail at the section above when the heading sits right under it and says the same thing: every crumb is then a link that goes somewhere, and there is no state to keep in step.
The trail around the fix has a few more choices.
- A last crumb in plain text: the ARIA Authoring Practices example keeps the last crumb as a link with
aria-current="page", as here. A crumb in plain text witharia-current="page"passes too, and saves a link that only reloads the page. - Hidden text instead of the attribute: where a theme or a content system lets you change a crumb's text but not its attributes, add visually hidden text such as "(current page)" inside it, as navigation that marks the current page only by its look explains for menus.
- Separators: draw them in CSS with no text, as a border or a background image, or put them in markup inside
aria-hidden="true". Text incontent, such as"/"or"›", is read by screen readers in most browsers. - The name: "Breadcrumb" is enough, because the screen reader adds "navigation" itself; see navigation landmarks that all sound the same.
- Lists: VoiceOver in Safari can drop the list role from a list whose markers CSS has removed, but it keeps it for a list inside a
nav, as here. A trail kept outside anavneedsrole="list"on itsol. - Single-page apps: when a route change swaps the page without loading it, the trail must be rebuilt and
aria-currentmoved with it; see single-page app route changes that are never announced.
Keep the current crumb visible in a Windows contrast theme. Forced colors give every link the same colour, so a crumb told apart only by its grey looks like the others; one that also has no underline, or is set in bold, still stands apart.
Fixing this with an AI coding assistant? Get this guide as Markdown, or get every guide in your coding agent.
Verify the fix
5 checks, no mouse.
Test with: Screen reader, Keyboard, Forced colors
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the shared breadcrumb component changes.
Limits
This is a starting pattern, not a guarantee for every site. Screen readers word aria-current and landmarks differently, and how they read punctuation depends on their settings; test with the ones your visitors use. A trail only helps when it follows the site's real structure: one that changes with how someone arrived, or skips a level, leaves people as lost as none. The page links at the end of a long list have failures of their own; see pagination links that don't say which page or where they go. The site's main menu marks its current page with the same attribute; see navigation that marks the current page only by its look.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
References
- WCAG Understanding: info-and-relationships (opens in a new tab)
- WCAG Technique H97 (opens in a new tab)
- ARIA APG: breadcrumb (opens in a new tab)
- developer.mozilla.org: aria-current (opens in a new tab)
- design-system.service.gov.uk: breadcrumbs (opens in a new tab)
- aaron-gustafson.com: identifying-accessibility-data-gaps-in-codegen-models (opens in a new tab)
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.