Accessibility patterns

Accessible names, visually hidden text, and concise status announcements.

Visually hidden text

Use .visually-hidden to keep supplemental text available to assistive technology while removing it from the visual layout. The library supplies CSS only; the examples below use local catalog behavior.

Light and dark examples are identical. Shaded explanations mirror the hidden text for visual review; these noninteractive teaching aids are excluded from the accessibility tree to avoid repeating that text.

1. Announce filter results

Use a persistent, initially empty status region to report the result of a user action without moving focus. The visible list and count remain available to everyone.

The native category menu already announces its selected option. Our message adds only the result, such as “1 of 3 items shown.” The menu’s option names and keyboard instructions come from the browser and screen reader, separately from this message.

Choose one announcement source in an application: this catalog shows a hidden region for demonstration. If the visible result count already contains the complete message, give that visible element role="status" and omit the hidden duplicate. Use hidden status text when it adds a concise equivalent of information otherwise conveyed visually.

Light mode

3 items shown.

  • Apples
  • Carrots
  • Oats

Dark mode

3 items shown.

  • Apples
  • Carrots
  • Oats

<p class="visually-hidden" role="status" aria-atomic="true"></p>
<!-- Application code updates this existing node after filtering. -->

2. Give a repeated action context

The button visibly says “Edit”; its text includes the item name for assistive technology. Keeping the visible wording at the beginning also helps people refer to the control by its visible label.

Demo behavior: Edit only reports which item was chosen; it does not open an editor. That feedback region starts empty. In an application, implement the actual editing action and its focus behavior; do not copy this extra status announcement when the newly focused editor already communicates the change.

Light mode

  • Apples
  • Oats

Dark mode

  • Apples
  • Oats

<button type="button">Edit<span class="visually-hidden"> Apples</span></button>

3. Name an icon-only action

Hide only the label text inside the button. While the field has content, the clear button remains visible and keyboard accessible. This is an alternative to aria-label; existing close/clear buttons do not need to migrate just to use the utility.

Light mode

Dark mode

<button type="button" data-barba-variant="icon" data-barba-shape="icon">
  <svg aria-hidden="true" focusable="false" viewBox="0 0 24 24">…</svg>
  <span class="visually-hidden">Clear item name</span>
</button>

Implementation guidance

These are implementation rules for this library’s examples, with links for the underlying accessibility requirements. The utility changes visual presentation only; it does not add naming, live announcements, focus management, or application behavior.

Choose the right use

  • Keep field labels, instructions, errors, and essential status information visible. Use .visually-hidden for supplemental text or an equivalent of information already conveyed visually.
  • Apply the class to noninteractive text, never to a focusable control or a container holding controls. Do not add hidden, display:none, visibility:hidden, aria-hidden="true", or inert to that text or its ancestors. The empty field’s clear button is intentionally hidden as a whole because its action is unavailable.
  • Use the existing .skip-link for a skip link that becomes visible on focus. This utility never reveals itself. See Bootstrap’s distinction between hidden and focus-revealed helpers.

1. Status updates: one concise announcement

  • Prefer role="status" aria-atomic="true" on an existing visible result message when it already says everything needed. Otherwise keep one persistent, initially empty hidden status region in the DOM before updates. Do not conditionally mount a populated region and assume it will be announced.
  • Update that region’s text after the result is ready. Leave focus on the initiating control. The status role is already polite; do not add role="alert" or aria-live="assertive" for ordinary filtering.
  • Announce useful results with context, such as “1 of 3 items shown.” Do not repeat the native control’s selected option, or make the entire results list live. Use one live region per update; check ancestors and visible copies for accidental additional live regions.
  • Avoid identical rewrites caused by rerenders. This example suppresses an unchanged count; that is not a universal rule for distinct operations that happen to have the same result. Decide whether new feedback is needed for the actual action. For live search, coordinate announcements with settled results, including cancellation of stale requests, instead of speaking every keystroke.

Read W3C’s status-region technique and tests and which changes qualify as status messages. A focus change can already communicate a new context; it does not automatically need a second announcement.

2. Repeated actions: name the item

  • Use a native button type="button" for an action, or a link with a real destination for navigation. For the Edit button, append the item’s name in a hidden span, including a separating space. Expected names here: “Edit Apples” and “Edit Oats”. Keep that context synchronized with the displayed item and translate the complete phrase appropriately.
  • Keep the visible label in the accessible name, preferably at the beginning. Prefer visible context when it would help everyone distinguish actions.
  • Use one deliberate naming source. Do not add aria-label or aria-labelledby on top of these button contents: they can override the content-derived name. Hidden text alone does not label an unrelated input; retain its associated visible label.

Read W3C’s label-in-name guidance and accessible naming techniques and precedence.

3. Icon actions: name the purpose and preserve focus

  • Give the visible native button a concise action name such as “Clear item name”, “Close settings”, or “Remove Apples”; do not name it “X”. Use either hidden text or aria-label. Existing correctly named icon buttons need no migration. Mark the decorative SVG aria-hidden="true" focusable="false"; do not rely on its appearance or a tooltip as the button’s only name.
  • Keep the standard close/clear target and focus treatment. On clear, return focus to the input before hiding the button. Hide it when the input is empty. For a populated disabled or read-only field, retain a disabled X as in the inline-form examples; it must not change the value.
  • Application code must clear the authoritative value and run the same validation, filtering, and state synchronization used by other value changes. Keep visibility synchronized after typing, reset, and programmatic updates. The catalog has no application state; its local clear handler assigns input.value and explicitly dispatches an input event to synchronize the example. Assigning the value alone does not fire that event. Framework applications should use their normal state-update path.
  • Do not add an automatic “cleared” announcement merely because the button disappears. First check what the focused field already communicates. Close and remove actions need their own appropriate focus destination; do not blindly reuse the clear handler.

Read MDN’s icon-button naming guidance and how input events relate to programmatic changes.

Verify the implementation, not just the markup

  1. Inspect the accessibility tree: confirm the expected button names, associated field labels, and no decorative SVG names or duplicate live regions. The hidden spans should remain available without adding keyboard stops.
  2. Use keyboard activation for both Edit actions and Clear. After clearing, verify the value and application state are empty, focus is on the input, and Clear is absent from the tab order. Type again and verify it returns. Check disabled/read-only fields and reset paths when implementing them.
  3. With a supported browser/screen-reader combination, change the filter and confirm the result is announced without moving focus or unnecessarily repeating the selected category. Check rapid changes, no results, and equal-count results in the consuming application. Record the browser, screen reader, and versions tested.
  4. Check both themes, narrow layouts, zoom, and visible keyboard focus. Automated DOM checks cannot establish the actual speech sequence or guarantee accessibility. The shaded mirrors here are noninteractive teaching aids excluded from the accessibility tree; do not copy them into application markup.

Migration from Our List

After adopting the library release, replace only the duplicated sr-only and row-announcement hiding styles. Preserve semantics and application behavior, then review status-region mounting and duplicate announcements separately. A CSS replacement does not fix announcement timing.

Full markup, options, and customization reference