All writing

Accessibility · Enterprise

Accessibility Beyond Keyboard Nav: Live Regions, Focus and ARIA That Works

Tab order gets an app through most audits. It says nothing about whether a screen reader user can tell what just happened after they pressed a key.

Jaymin Maheta 8 min read
Share:
Person using assistive technology with a screen reader on a laptop

Passing an audit and being usable are different bars

Automated accessibility scanners catch missing alt text and low contrast reliably. They catch almost nothing about whether a screen reader user understands what just happened when a filter applied, a row got deleted, or a modal opened over content they were reading — because that requires actually listening to the page, not just parsing its DOM.

Keyboard-only navigation is the most visible and most tested part of accessibility, which is exactly why it tends to be the only part teams verify. The gaps live in the parts that don't show up on a tab-through: dynamic updates, focus after an action, and ARIA that describes something other than what's actually rendered.

Where dense UIs go quiet for screen reader users

Live regions for content that changes without navigation

A filtered table that updates in place is silent to a screen reader unless the result count sits in an `aria-live="polite"` region. Without it, the user has no idea anything happened.

Move focus deliberately after every action

Closing a modal, submitting a form, deleting a row — each should send focus somewhere specific and sensible, not leave it on a now-detached element or silently reset to ``.

ARIA roles must match real behavior

`role="button"` on a div that doesn't respond to Enter or Space is worse than no role at all — it promises interaction the element doesn't deliver, and the screen reader user finds out by trying.

Trap focus inside modals, release it on close

Tabbing out of an open modal into background content breaks the mental model of what's active. Trap focus while open; return it to the trigger element on close.

Loading states need an announced label

A spinner with no accessible name is invisible to a screen reader. `aria-busy` plus a labeled live region turns "nothing is happening" into "results are loading."

Test with an actual screen reader, regularly

NVDA or VoiceOver on the real feature, not just an axe scan in CI. Automated tools catch structural violations; only listening catches whether the experience makes sense.

Complex widgets need their own ARIA pattern, not an ad-hoc one

Comboboxes, tab panels, tree views, and data grids each have an established ARIA authoring pattern from the WAI-ARIA Authoring Practices Guide — expected roles, expected keyboard behavior, expected relationships between elements. Inventing a custom interaction for one of these from scratch, without checking the pattern first, is where most of the subtle breakage happens.

The takeaway

Keyboard support is the visible 20% of accessibility. Live regions for dynamic content, deliberate focus management after every action, and ARIA that matches real behavior are the invisible 80% — and the only way to verify them is to actually listen with a screen reader, not just run a scanner.

Let's talk about your product