Test your website →

Blog

Accessible Modals: The Popup That Traps Screen Readers

A badly built modal splits your page into two layers, strands screen reader users in the wrong one, and the platform already fixed this if you let it.

If you want to understand why accessibility bugs happen, the modal dialog is the perfect specimen. It’s the most common custom widget on the web, it looks trivially simple, and building it correctly is genuinely hard. Nearly every site has one, and most of them are broken in ways their owners cannot see.

Here’s the illusion. To a sighted person, a modal is obviously modal. The popup floats in front, the page behind dims, and the dimming is a message: that stuff is off limits for now, deal with this first. Your eyes get the whole story in a glance.

A screen reader gets none of it. A screen reader experiences a page roughly as a sequence of elements, and a naive modal is just more elements appended somewhere in that sequence, usually at the very end. The dimming is a visual effect with no meaning in the sequence. So the blind user is left in a strange split world. The page they were reading is still there, still fully readable, but the controls in it no longer work because a transparent overlay is eating the clicks. Meanwhile the dialog that actually demands their attention is somewhere else entirely, possibly after hundreds of elements they’d have to step through to find it. Nothing tells them it appeared. They keep reading a page that has silently stopped being the real page. If the modal is your email capture, your login, or your checkout, that user is done, and you’ll record it as an abandoned session with no idea why.

Getting a modal right means making the experience of the sequence match the experience of the eyes, and that comes down to a handful of behaviors. When the dialog opens, keyboard focus must move into it, so the user is taken to the new thing rather than left to hunt for it. While it’s open, focus must stay inside: pressing Tab past the last control should wrap around to the first, not wander back into the dimmed page. This is called a focus trap, and it’s the rare case where trapping the user is the correct behavior, because it makes the keyboard world agree with the visual world about what’s currently interactive. The content behind the dialog should be hidden from assistive technology too, not just dimmed, so a screen reader exploring the page can’t slip into the unreachable layer. Escape should close the dialog, because that’s the exit everyone reaches for. And when it closes, focus must return to the element that opened it, so the user resumes where they left off instead of being dumped back at the top of the page. Miss that last step and every dialog interaction costs the user their place.

That’s a lot of behavior for a floating box, and for years every team reimplemented it, mostly badly, with divs and z-index and hope. The part that deserves to be better known is that the platform has since absorbed almost all of it. HTML has a native dialog element, and when you open it with showModal(), the browser handles the hard parts: focus moves in, the Escape key works, the rest of the page is made inert so neither clicks nor screen readers can reach it. What took a few hundred lines of fragile JavaScript is now mostly one element and one method call, supported in every current browser. Yet sites keep shipping hand-rolled div modals, sometimes freshly written in 2026, because the old pattern is what everyone knows and what old tutorials teach. This happens all over web development: the platform quietly fixes something, and the ecosystem keeps using the workaround for a decade out of habit.

There’s a business observation buried in this. Modals are not decorative. Companies put their highest-stakes interactions in them: sign up, pay, confirm, subscribe. A broken footer hurts nobody. A broken modal sits directly on the path to revenue. So the accessibility bug that’s hardest to notice from the inside, because your whole team is sighted and mouse-driven, is parked on top of the exact step where visitors become customers. When I run audits with GazeSite I pay attention to dialogs for this reason. The screenshot shows a normal-looking popup; the HTML underneath shows whether it’s a real dialog or a div wearing a costume, and the difference decides whether some fraction of visitors can pay you at all.

The test, as usual, is cheap. Open your most important modal and press Tab a dozen times, watching where the focus indicator goes. If it escapes into the dimmed background, your modal is broken. Press Escape; if nothing happens, it’s broken. Close it and see whether focus lands back on the button that opened it. Ten seconds per check, no special tools. And if you find problems, the fix in 2026 is usually not to patch your focus-trap code. It’s to delete it and use the element the browser has been offering you all along. The best accessibility code, like the best code generally, is the code you no longer have to write.

More articles

← All posts