UX Design

Screen Reader Compatibility: Use HTML, ARIA and a Repeatable Test

By EZUD Published · Updated

Screen Reader Compatibility: Use HTML, ARIA and a Repeatable Test

Start with native HTML, give controls clear names and keep their exposed states synchronized with what they do. Use ARIA to supply semantics the component needs, then verify the result in the browser and screen-reader combinations your service supports.

A useful review follows a real task. Find a section, open its details, change an option and submit the result. At each step, check whether the user can identify the control, understand its current state, operate it and discover what changed.

Choose the element before adding a role

Use a button for an action, a link for navigation and the appropriate native form control for data entry. Headings, lists and landmarks give a document structure that screen readers can navigate. Preserve that structure in the HTML rather than relying on visual size or spacing alone.

The WAI-ARIA Authoring Practices Guide explains that assigning a role does not supply keyboard behavior. A generic container with a button role still requires the author to implement the expected interaction. Native elements reduce that implementation burden and make the intended behavior easier to recognize in code review.

For a custom component, choose its interaction pattern first. An expandable section, a tab set and a modal dialog expose different relationships and require different focus behavior. A role should describe the behavior you have actually built.

Inspect the name, role and state

Use the browser’s accessibility inspector to examine a component’s exposed name, role and state. Compare them with the visible interface. A control labeled “Save delivery choice” should expose that wording in its name, rather than an unrelated internal label.

WCAG 2.5.3 requires the accessible name to contain the visible text label for controls with such labels. Keeping the visible label at the start of the name is useful for people who activate controls by speaking their labels. Add clarifying context only where needed and avoid replacing a good visible label with a longer, conflicting aria-label.

Check state changes as well as the initial state. A checkbox should expose whether it is checked. An expandable control should expose whether it is expanded. A value control should expose the current value using the semantics appropriate to that element.

A small disclosure pattern

This example shows one button controlling a section of details. Use unique IDs when placing more than one instance on a page.

<button type="button" id="delivery-toggle"
        aria-expanded="false" aria-controls="delivery-details">
  Delivery details
</button>
<div id="delivery-details" hidden>
  <p>Choose a delivery method during checkout.</p>
</div>
const toggle = document.getElementById('delivery-toggle');
const details = document.getElementById('delivery-details');
toggle.addEventListener('click', () => {
  const expanded = toggle.getAttribute('aria-expanded') === 'true';
  toggle.setAttribute('aria-expanded', String(!expanded));
  details.hidden = expanded;
});

The native button supplies Enter and Space activation. The handler keeps visibility and the expanded state aligned. Focus remains on the button, allowing the user to close the section or continue through the document. The APG disclosure pattern documents this behavior; use a dialog or another pattern when the interaction calls for a different focus model.

Test the collapsed and expanded versions in the accessibility tree and with a screen reader. Confirm that hidden content is unavailable while collapsed and that opening the section makes its content discoverable in the expected reading order. Then test a second instance to catch duplicate-ID mistakes.

Keep descriptions connected to controls

Use a label for the control’s name and a separate description for a hint or error when needed. In a form, aria-describedby can refer to the IDs of those explanatory elements. Keep the wording short enough to help at the point of use.

Review the relationship after validation. When an error is resolved, remove or update the error reference and invalid state. Otherwise the visual interface may look repaired while the screen reader continues to announce an obsolete problem.

Avoid putting an entire panel’s contents into the name of one button. A long name can make repeated navigation cumbersome and obscure the actual action. Keep detailed information in the document where users can read it deliberately.

Announce status without moving focus unnecessarily

For an update such as a saved preference or a result count, use a suitable status mechanism so assistive technology can report the change. WCAG 4.1.3 addresses status messages that can be presented without receiving focus. A routine update often works well in a pre-existing role="status" region whose text changes when the action completes.

Choose one clear message and update it when the outcome is known. Announcing every keystroke, loading fluctuation and repeated validation check can make the task harder to follow. Reserve more interruptive announcements for situations that need that urgency.

For a new page or a modal, use the appropriate navigation or focus behavior instead. Decide how the user discovers the new context, the main content and the available actions. Test the result from the user’s previous location, not only by loading the final state directly.

Test reading and interaction separately

Record the operating system, browser and screen-reader versions. Include the settings or mode that affect navigation. Use the screen reader’s own guide to learn its document navigation, form interaction and command-help features before interpreting an unexpected result as a page defect.

In a reading pass, inspect the page title, headings, landmarks, link names and content order. In an interaction pass, operate forms, disclosures, dialogs and dynamic results. Listen for names and state changes, and verify that the task reaches the expected outcome.

NVDA’s user guide describes browse mode, focus behavior and web navigation for Windows. Use comparable official documentation for other supported screen readers. Test more than one relevant combination when the service supports them, especially for custom widgets and complex dynamic updates.

Record evidence that helps the next repair

Use a report with five fields: environment, starting state, steps, expected information and observed information. Include the exact control and the first point where the user loses the task. A short speech transcript or recording can help when collected with appropriate consent and without exposing personal data.

Check the implementation’s semantics and event handling before adding more ARIA. If the state is wrong in the accessibility tree, repair that relationship. If the semantics are correct but a supported combination behaves unexpectedly, reduce the issue to a small reproducible component and investigate that combination.

After the fix, repeat the complete task and check other instances of the shared component. Keep the expected name, role, state and keyboard behavior in its documentation. This gives future changes a clear behavior to preserve.

Sources