Applied Filter Chips and Removal
Permalink to "Applied Filter Chips and Removal"Applied filter chips summarise what is filtering a table — “Status: Overdue ×”, “Region: North ×”, “Amount: 500–2,000 ×” — and let users remove one with a click. They are often built as tiny buttons with an “×” and no name, removed from the DOM on click so focus falls to the page body. For screen reader users, chips are the best summary of the current view, if they can find them and hear what each one does.
This guide belongs to accessible filtering and faceted search.
Spec reference
Permalink to "Spec reference"- SC 1.3.1 (A) — chips grouped as a list with a heading or label.
- SC 2.4.3 Focus Order (A) — focus moves somewhere logical when a chip disappears.
- SC 4.1.2 (A) — remove buttons named “Remove filter Status: Overdue”.
- SC 4.1.3 (AA) — result count after removal announced.
- SC 1.4.11 (AA) — chip boundaries and remove icons meet 3:1.
When to use — and when not to
Permalink to "When to use — and when not to"Use chips whenever filters are set in a panel, popover or column menu that is not always visible; chips keep the current state visible near the results.
Do not use chips as the only way to set filters; they are a summary and a removal shortcut. The misapplication: chip remove buttons with aria-label="Remove" repeated five times, so screen reader users hear “Remove, button” with no idea which filter goes.
Annotated code example
Permalink to "Annotated code example"<section aria-labelledby="chips-h">
<h2 id="chips-h" class="small">Filters applied (3)</h2>
<ul class="chips">
<li class="chip">Status: Overdue
<button type="button" aria-label="Remove filter Status: Overdue">×</button></li>
<li class="chip">Region: North
<button type="button" aria-label="Remove filter Region: North">×</button></li>
<li class="chip">Amount: 500–2,000 kroner
<button type="button" aria-label="Remove filter Amount: 500 to 2,000 kroner">×</button></li>
</ul>
<button type="button" class="clear-all">Clear all filters</button>
</section>
<p role="status" id="result-count"></p>
function removeChip(i) {
removeFilter(i);
const buttons = chipButtons(); // after re-render
const target = buttons[i] || buttons[i - 1] || document.getElementById('chips-h');
if (target.id === 'chips-h') target.tabIndex = -1;
target.focus(); // SC 2.4.3
status.textContent = `Filter removed. ${count()} invoices match.`; // SC 4.1.3
}
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"| Action | Focus after | Announcement |
|---|---|---|
| Tab into chips | First remove button | “Remove filter Status: Overdue, button” |
| Enter on a remove button | Next chip’s button | “Filter removed. 126 invoices match.” |
| Remove the last chip | Previous chip or heading | Same |
| Clear all | Heading or first filter control | “All filters cleared. 412 invoices.” |
Step-by-step implementation
Permalink to "Step-by-step implementation"- Derive chips from filter state. Chips should be rendered from the same state as the filter panel, never maintained separately, so they cannot drift.
- Name remove buttons fully. Include the filter name and value in each remove button’s accessible name. Visible text can stay short; the name carries the detail.
- Plan focus before removing. Compute the next target before re-rendering: the chip that will take the removed chip’s place, the previous chip if it was last, or the chips heading if none remain.
- Announce the count. After removal, announce the new number of results in a polite status region.
- Provide clear all. Put “Clear all filters” after the chips; after using it, move focus to the filter panel’s first control or the heading.
Integration context
Permalink to "Integration context"Focus rules for clearing filters are covered in clearing filters without losing keyboard focus. Count announcements follow announcing filter result counts with aria-live. Range values come from range slider filters for numeric columns. Naming icon buttons is covered in naming icon-only row action buttons.
Gotchas
Permalink to "Gotchas"Chips as toggle buttons. Some designs make the whole chip a toggle; then use aria-pressed and name the chip, but removal-only chips are simpler.
Listbox or grid roles for chips. A plain list with buttons is enough; composite roles add arrow-key expectations you must then implement.
Overflowing chip rows. When there are many chips, wrap them rather than hiding them behind horizontal scroll.
Edge cases
Permalink to "Edge cases"- Filters set from the URL. On load with filters in the URL, render chips and announce nothing; the heading count is enough.
- Dependent filters. Removing a parent filter (Country) may remove children (City); announce both removals.
- Very long values. Truncate visible chip text, but keep the full value in the button’s name.
Worked example
Permalink to "Worked example"A marketplace admin table showed filter chips with “×” buttons labelled “Remove”. Removing one destroyed the button and dropped focus to the top of the page, so keyboard users had to tab through forty controls to get back. The team named each remove button with its filter, moved focus to the next chip after removal, added a heading with the filter count and a polite count announcement. Screen reader users started using chips as their main way to understand the current view.
Common mistakes
Permalink to "Common mistakes"- Remove buttons all named “Remove”.
- Focus lost after removal.
- Chips that do not match the panel.
- No clear-all control.
Testing checklist
Permalink to "Testing checklist"Testing it with a screen reader
Permalink to "Testing it with a screen reader"In NVDA, navigate by headings to “Filters applied (3)” and press Tab to reach the first remove button; it should announce the full filter name. Press Enter and listen for the count message, then confirm with Insert+Tab that focus is on the next chip’s button. Remove chips until none remain and check that focus lands on the heading rather than the document body. Use VoiceOver’s rotor to list buttons and verify that each remove button is distinguishable by name. Repeat with JAWS and check that the list is announced with its item count.
Design system notes
Permalink to "Design system notes"Provide a filter summary component that takes filter state and generates chips, names, focus handling and the status message, so every table gets the same behaviour.
Writing chip labels
Permalink to "Writing chip labels"Chip text should read like the filter control that set it: the column or facet name, a colon, then the value. “Status: Overdue” is clearer than “Overdue” when several facets share values such as “None” or “Other”. For ranges, write both ends and the unit: “Amount: 500–2,000 kroner”. For multi-select filters, either show one chip per value (“Region: North”, “Region: South”) so each can be removed alone, or one chip with a count (“Region: 3 selected”) that opens the filter when activated. Keep the order of chips the same as the order of filters in the panel, so users who learn one layout can predict the other. And when a filter is set by default — for example “Status: Open” on first load — show it as a chip too, so nobody wonders why closed items are missing.
FAQ
Permalink to "FAQ"Should chips be in a list?
Yes. A list tells screen reader users how many filters apply.
Can chips be links?
Only if removing a filter navigates to a new URL; buttons are usual.
Where should focus go after clear all?
To the filter panel’s first control or the chips heading, whichever users expect next.
Should I announce the removed filter name?
The count is essential; repeating the removed filter is optional but helpful.
Is the "×" glyph acceptable?
Visually yes, if the button’s accessible name is descriptive and the glyph meets contrast.
Do chips replace the filter panel?
No. They summarise and remove; editing a filter happens in its control.
Related
Permalink to "Related"- Clearing filters without losing focus — focus rules
- Range slider filters — numeric filters
- Announcing filter result counts — count messages