Skip to content
easeweb
Search topics

Filter links that don't say which is chosen or what changed

Category links above a product list redraw it in place and fill the chosen pill by a class, so a screen reader hears no change and no chosen filter.

WCAG 2.2
SC 4.1.2A
Required by
Section 508 · EN 301 549 (EU)
Broken link.classList.add('is-active');
The accessibility problem illustrated: No vision:Did anything change?
01

The problem

Screen reader users press a filter and hear nothing, so they can't tell that the list changed or which filter is now chosen.

02

Try it

Choose a filter and listen for what is said.

Tab to Mugs and press Enter. The panel shows what a screen reader says. After each press, Tab along the filters again: is the chosen one ever called current, and is the change ever heard?

Broken Can you fix this?

BrokenFilter links redrawn in place, marked by a class

Tableware

  • Enamel mug
  • Stoneware mug
  • Side plate
  • Dinner plate
  • Pasta bowl
  • Cereal bowl

Screen reader says:

(Tab to a filter, then press Enter)

A recreated demo. The broken version is intentionally inaccessible.

03

The fix

Mark the chosen filter, and say what the page now shows.

Before
BrokenFilter links redrawn in place, marked by a class
<title>Mugs | Tableware</title>…<ul class="filters">  <li>    <a href="/shop">All</a>  </li>  <li>    <a href="/shop?category=mugs" class="is-active">Mugs</a>  </li>  <li>    <a href="/shop?category=plates">Plates</a>  </li>  <li>    <a href="/shop?category=bowls">Bowls</a>  </li></ul><ul id="products">…</ul>
What is wrong2 points
  • The is-active class fills the Mugs pill and does nothing else: a screen reader reads "Mugs, link", the same as the other three.
  • The script stops the page load and redraws the list in place, so nothing is read after the press: no new page title, and no message.
After

Mark the chosen link, and say what changed

<title>Mugs | Tableware</title>…<ul class="filters">  <li>    <a href="/shop">All</a>  </li>  <li>    <a href="/shop?category=mugs" aria-current="page">Mugs</a>  </li>  <li>    <a href="/shop?category=plates">Plates</a>  </li>  <li>    <a href="/shop?category=bowls">Bowls</a>  </li></ul><p id="filter-status" role="status" class="visually-hidden"></p><ul id="products">…</ul>
How it is fixed5 steps
  1. Replace the class with aria-current="page" in the markup the server sends. The link's address is the page being shown, and a screen reader reads it as the current page, with something like "Mugs, current page, link".
  2. Draw the filled look from [aria-current="page"], so the pill that looks chosen and the one that is announced are always the same.
  3. Put an empty role="status" region under the filter row, hidden visually. It is in the page from the start and outside the list that is redrawn, so writing into it is a change the browser reports.
  4. Once the new list is in, move aria-current to the pressed link and write "Now showing: Mugs" into the region. The screen reader finishes what it is saying, then reads it, and focus stays on the pill, ready for the next filter.
  5. Do nothing when the pressed link is already the current one, so the list isn't fetched again for the filter in force.

This fixes the Before and passes 4.1.2: the chosen filter is marked in code, and the change is reported as it happens. The mark is what 4.1.2 asks for, but whether a screen reader speaks a change to aria-current on the link that has focus is not something tested here, so the message says it in words.

04

Design ideas

A chosen filter can take many looks and still be heard.

Four more ways to draw the filter row, in the guide’s own ink. Click a filter to move the choice, and Tab along the rows: three mark the choice where a screen reader finds it, and one only shows the change by moving.

In the design file

  • Draw the chosen filter as its own state, marked by a tick, a bar or bold text as well as any fill, because a Windows contrast theme removes fills.
  • Draw hover and focus on every filter, the chosen one included, since each stays a link.
  • Write beside the row the words the page says after each press, even when they are only read aloud.

Passes

  • Chip with a tick The chosen chip gains a tick and bold text in #1d1d1f, 14.39:1 on its pale #e6eef8 fill. The fill is only 1.17:1 against the page, so it is decoration; the tick and the weight carry the choice, and both stay in a contrast theme.
  • Underlined row, like tabs The filters sit on a hairline, the chosen one bold with a 3-pixel bar under it in #1d1d1f, 16.83:1 on white. The others are #5f6368, 6.05:1, but only 2.78:1 from the chosen ink, so the bar and the weight do the work. It looks like tabs and stays a row of links, with no arrow keys to learn.
  • Now showing: Mugs

    A “Now showing” line under the pills The guide’s pills, with a line under them in #5f6368, 6.05:1, that changes to “Now showing: Mugs” on each press. Sighted visitors on a phone see the change without scrolling to the list, and the same line is what a screen reader hears.

Fails

    • Enamel mug
    • Stoneware mug
    Grid that shuffles into placeWCAG 4.1.2 The tiles glide to their new places in 0.4 seconds, a movement that shows the change and stops. But it is the only report: the filled pill is drawn from a class, and nothing is said, so a screen reader hears “Mugs, link” and no change at all.
05

Verify the fix

5 checks, no mouse.

Test with: Screen reader, Keyboard, Forced colors

0 of 5 checked

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the filter component, the list template or the page layout changes.

How screen readers handle role="status" and aria-current="page"

Limits

Live regions behave differently across screen readers and browsers, and a polite message can be dropped if people keep pressing. This guide covers one row of links that each choose one filter. Filters people combine, several ticked at once, are usually checkboxes, and announcing their results is covered in search and filter results that update without a word. A link that replaces the whole view of a single-page app is covered in single-page app route changes that are never announced, and the current page in a site's menu in navigation that marks the current page only by its look. Test your real filters, with their sorting and pagination, with the screen readers your users use.

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.

EaseWeb service

Fixed it? Keep it from coming back.

I turn guides like this one into rules your coding agents follow and checks your CI runs. Then I retest by hand with a keyboard and screen readers, periodically.

See the service