DEV Community

137Foundry
137Foundry

Posted on

How to Test Modal Dialog Accessibility With Keyboard Navigation and Screen Readers

A modal dialog that looks fine with a mouse can fail completely for users who navigate with a keyboard or a screen reader. This is one of the most common accessibility gaps in web applications, and it is also one of the most testable: the failure modes are concrete, the tools are free, and a thorough test takes under 30 minutes per modal.

Here is a practical walkthrough of how to test modal accessibility using only the tools you already have on your machine, the standards published by the W3C and supporting bodies, and a methodical run through the failure modes that show up in production.

Whiteboard with sketches and notes
Photo by Kaleidico on Unsplash

Step 1: Keyboard-Only Test First

Before reaching for a screen reader, run the modal through keyboard navigation alone. Most accessibility failures fail this test first, and the screen reader testing builds on top of it.

Open the modal using only the keyboard. Tab to the triggering control, press enter or space, and confirm the modal opens.

When the modal opens, focus should move into it automatically (usually to the first interactive element or to the close button). If focus stays on the trigger button or jumps somewhere unrelated, the focus management is broken.

Tab forward through every interactive element in the modal. Tab should cycle within the modal indefinitely. If tab ever escapes to elements behind the modal, the focus trap is broken.

Press shift-tab to go backward. The cycle should reverse cleanly. Shift-tab from the first focusable element should return to the last, not escape backward into the page.

Press escape. The modal should close. If escape does nothing, the universal expectation is broken.

When the modal closes, focus should return to the element that triggered it. If focus jumps elsewhere (often to the top of the document), users lose their place and have to navigate back.

Run this entire sequence without touching the mouse. Every step should work, and the experience should feel natural.

Step 2: Run the Same Test with a Screen Reader

The screen reader test layers on top of keyboard testing. The keyboard navigation should still work; the screen reader is reading aloud what is happening at each step.

On Windows, install NVDA, which is free. On Mac, VoiceOver is built in (Cmd+F5). On iOS, VoiceOver is in Settings > Accessibility. On Android, TalkBack is in Settings > Accessibility.

Open the modal with the keyboard while the screen reader is running. Listen for:

The dialog announcement. When the modal opens, the screen reader should announce that a dialog or alertdialog has appeared. If it announces something generic like "group" or stays silent, the ARIA role is missing or wrong.

The dialog label. The screen reader should read the modal's title or label. This requires aria-labelledby pointing to the heading element, or aria-label with the title string. Without either, the user gets a context-free dialog announcement.

The dialog description. A meaningful description should follow the title, usually via aria-describedby pointing to the body text. Without this, the screen reader user has to navigate manually to find out what the modal is for.

Focus content. As the user tabs through, the screen reader should announce each interactive element's label and role. Buttons should say "button," form fields should say their label and type, and so on.

Close announcement. When the modal closes, the screen reader should announce returning to the previous context. The user should not have to figure out from silence whether the modal closed.

Step 3: Test on Mobile

Mobile accessibility for modals has additional failure modes beyond desktop. Test on a real mobile device, not just a desktop browser at a mobile viewport.

Soft keyboard interaction. If the modal contains a text input, tap into it on a real phone. The soft keyboard should appear without pushing the input off-screen or breaking the layout. Test that scrolling within the modal still works while the keyboard is open.

Back gesture. On Android, swipe back. On iOS, swipe from the left edge or use the page back. The modal should close, not the page. If the page navigates away while the modal is open, the back-button integration is missing.

Touch target size. Tap targets should be at least 44 pixels. Smaller targets are misclick generators on phones.

Screen reader on mobile. Run the modal through TalkBack or VoiceOver on the actual device. Mobile screen readers have different navigation gestures than desktop ones, and a modal that works on desktop screen readers can fail on mobile screen readers.

The W3C documentation on mobile accessibility covers the specific touch and gesture expectations, and MDN covers the technical implementation of the mobile-specific patterns.

Sticky notes wall planning
Photo by Polina Tankilevitch on Pexels

Step 4: Run the Automated Tools, But Do Not Trust Them

Tools like axe DevTools (browser extension) and Lighthouse (Chrome DevTools) catch a subset of accessibility issues automatically. They are useful as a first pass: they catch missing ARIA attributes, invalid markup, and obvious color contrast failures. They do not catch focus management bugs, focus trap failures, or screen reader announcement quality.

A clean automated audit is necessary but not sufficient. The keyboard and screen reader testing in steps 1 and 2 catches what the automated tools miss. Teams that rely only on the automated tools regularly ship modals that pass the audit but fail real users.

The a11y Project maintains a current list of automated and manual testing tools, plus the failure categories each one catches well or misses. Reading their tool comparison is worth the 20 minutes the first time.

Step 5: Document the Test Results

For any modal that ships, keep a simple record of which tests passed and which did not. The record helps with:

  • Future regressions (you know the baseline)
  • Audit responses (you can show the testing was done)
  • Onboarding new team members (they can see the standard you hold modals to)

A simple checklist works:

  • Keyboard: open / focus moves in / tab cycles / shift-tab cycles back / escape closes / focus returns
  • Screen reader: dialog announced / label read / description read / content navigable / close announced
  • Mobile: works with soft keyboard / back gesture closes / tap targets sized / screen reader works on device
  • Automated: axe DevTools passes / Lighthouse a11y score

This takes 20-30 minutes per modal the first time and much less on subsequent runs. The cost is small compared to a real accessibility incident or a public complaint.

Common Failures and Their Fixes

A few patterns of failure that show up repeatedly:

No focus trap, focus escapes to background. Either implement a focus trap manually (track first/last focusable elements and redirect tab) or use a vetted component library that handles it. Custom implementations from scratch frequently miss edge cases.

Focus does not return on close. Store the focused element when the modal opens (document.activeElement) and call .focus() on it when the modal closes.

Missing or wrong ARIA role. The modal element needs role="dialog" or role="alertdialog". The latter is for modals that need immediate attention (errors); the former is for normal dialogs. Use aria-modal="true" to tell assistive tech the background is inert.

Wrong label association. aria-labelledby should point to the ID of an element containing the dialog title. Inline strings via aria-label work as a fallback but lose translation flexibility.

Soft keyboard breaks layout. Use the visualViewport API to detect keyboard appearance and adjust the modal's max-height or scroll behavior accordingly.

The 137Foundry web development team handles accessibility audits on modal-heavy applications regularly, and the failure list above accounts for most of what comes up in production reviews. The longer 137Foundry guide on modal dialog design covers the architectural decisions behind these implementation patterns.

The Underlying Standard

Accessibility for modals is not a stylistic preference. It is a measurable standard with concrete failure modes, and the cost of meeting it is small compared to the cost of failing it. A modal that meets the keyboard, screen reader, and mobile tests above is genuinely accessible. A modal that does not is not, regardless of how much developer attention went into the visual design.

Most modals that ship today fail at least one of these tests. The fixes are usually straightforward once the failure is identified. The hardest part is committing to the testing in the first place.

A Practical Workflow

  1. Build the modal
  2. Run the keyboard-only test before merging
  3. Run the screen reader test before shipping to production
  4. Run the mobile device test on the first user-facing release
  5. Document what passed and what did not
  6. Re-test on any structural change to the modal or its containing component

This workflow catches most accessibility failures before users do. It also produces a paper trail that protects the team if an accessibility issue is raised later. The combined cost is much smaller than most teams expect, and the resulting modals are dramatically better.

Top comments (0)