Accessible Pop-ups: Focus, Keyboard and Screen Reader Basics

A pop-up that a mouse user can close in one click can trap a keyboard user, or appear silently for someone using a screen reader. This guide explains the W3C pattern for accessible modal dialogs in plain terms, shows what each rule means for a marketing pop-up, gives you a short test you can run in ten minutes, and is upfront about where marketingLABO’s own banners meet the pattern today and where they don’t.

Updated

Who a pop-up can lock out

Accessibility comes down to one question: can every visitor notice the pop-up, understand it, act on it and get rid of it? Four groups run into trouble most often:

  1. Keyboard users — people who can’t use a mouse, or prefer not to. They move with Tab and Shift+Tab and expect the Escape key to close a dialog. If the close control can’t be reached with Tab, the pop-up can only be closed with a mouse.
  2. Screen reader users — people who hear the page read aloud. If nothing tells the screen reader that a dialog opened, they keep reading the page behind it and may never know the offer exists. If the offer’s text is part of an image with no text alternative, there is nothing to read.
  3. People using zoom or magnifiers — they see only part of the screen at once. A dialog that opens off to one side, or a close button outside the visible area, can be easy to miss.
  4. People with limited fine motor control — small, tightly placed close buttons are hard to hit, on touch screens especially.

The reference: W3C’s modal dialog pattern

The W3C’s ARIA Authoring Practices Guide (APG) publishes a Dialog (Modal) Pattern that describes how a modal dialog should behave for keyboard and screen reader users. A pop-up that covers the page is a modal dialog in this sense. The core rules, quoted from the APG and paraphrased for pop-ups:

APG ruleWhat it means for a pop-up
“When a dialog opens, focus moves to an element contained in the dialog.”When the pop-up appears, keyboard focus jumps into it, so the next Tab lands on the pop-up’s own controls rather than on a link hidden behind it.
Tab “moves focus to the next tabbable element inside the dialog”; from the last element it wraps to the first. Shift+Tab does the reverse.While the pop-up is open, Tab cycles through its controls only (email field, submit button, close button) and does not wander off into the page behind.
Escape “closes the dialog.”Pressing Esc dismisses the pop-up, the same as clicking its close button.
“When a dialog closes, focus returns to the element that invoked the dialog.”After closing, the visitor continues from where they were. For a pop-up that opened on its own, return focus to a sensible spot — usually where the visitor was before it appeared.
The container has role="dialog".Screen readers announce “dialog” when it opens.
aria-modal="true" on the container.Tells assistive technology that the content behind is not available right now. The APG advises using it only when the page behind really is blocked and visually obscured.
aria-labelledby pointing to a visible title (or an aria-label).The dialog has a name, for example “Get 10% off your first order,” so a screen reader can say what opened.
aria-describedby (optional).Can point to a short description. The APG advises leaving it out when the content is complex, such as lists or several paragraphs.

These rules line up with several success criteria in WCAG 2.2 (W3C Recommendation, December 12, 2024), which is the standard most accessibility policies and audits refer to. The ones a pop-up most often fails:

WCAG 2.2 criterionLevelHow pop-ups typically fail it
1.1.1 Non-text ContentAThe offer is an image with no text alternative, or with alt text that just says “banner.”
1.3.5 Identify Input PurposeAAThe email field doesn’t declare what it collects, so browsers can’t autofill it reliably.
1.4.3 Contrast (Minimum)AALight gray text on a pastel background; text below the 4.5:1 ratio.
1.4.11 Non-text ContrastAAA faint close icon or input border below 3:1 against its background.
2.1.1 KeyboardAThe close control only responds to clicks.
2.1.2 No Keyboard TrapAFocus gets into the pop-up and there is no keyboard way out. (A focus loop inside a dialog is fine as long as Escape or a close button lets you leave.)
2.4.7 Focus VisibleAACustom styles remove the focus outline from buttons and fields.
2.4.11 Focus Not Obscured (Minimum)AAA sticky bar or floating banner covers the element that currently has focus.
2.5.8 Target Size (Minimum)AAA close button smaller than 24×24 CSS pixels with other targets close by.
3.3.1 Error Identification / 3.3.2 Labels or InstructionsAThe field’s only label is placeholder text, and errors are shown only by color.
4.1.2 Name, Role, ValueAA “✕” built from a span has no role and no name; a screen reader may read “times” or nothing at all.
4.1.3 Status MessagesAA“Thanks, check your inbox” appears visually but is never announced.

Focus: move it in, keep it in, bring it back

Focus handling is invisible to mouse users, which is why custom pop-ups so often get it wrong. Three moments matter.

On open. Move focus into the pop-up. For a short promotional dialog, the APG’s general advice is the first focusable element, but you can choose. MDN’s guidance on the native dialog element suggests putting initial focus on the close button when nothing in the dialog needs more immediate interaction, or on the dialog itself. For an email sign-up pop-up, focusing the email field is reasonable; for a coupon announcement, the close button or the dialog container is often better, because it doesn’t pressure the visitor into acting.

While open. Keep Tab and Shift+Tab inside the pop-up, and make the content behind it unavailable — visually (an overlay) and to assistive technology. If you use the native <dialog> element with showModal(), the browser does this for you: according to MDN, “Everything outside the modal dialog is inert and interactions outside the dialog are blocked.”

On close. Return focus. If the visitor clicked a “Get the discount” link that opened the pop-up, focus goes back to that link. If the pop-up opened on a timer or scroll trigger, there is no invoking element, so return focus to whatever had it before — or, if nothing did, leave it at the top of the main content. What you must avoid is focus landing on an element that was just removed from the page; many browsers then reset to the top of the document, and the keyboard user loses their place.

Keyboard: Tab, Shift+Tab and Escape

Every action in the pop-up — closing, typing, submitting, following the main link — must work from the keyboard:

  1. Use real buttons. A <button> is focusable and responds to Enter and Space by default. A <div> or <span> with a click handler is neither, unless you add a role, a tabindex and key handlers yourself.
  2. Support Escape. Keyboard users expect it. MDN puts it directly: “Keyboard users expect the Esc key to close modal dialogs; ensure that this behavior is implemented and maintained.” The native dialog element opened with showModal() handles Escape by default.

Screen readers: role, name and real text

For a screen reader user, a pop-up that isn’t announced is invisible. Three things make it perceivable:

  1. A role. role="dialog" on the container (or the native <dialog> element, which has it built in). Use aria-modal="true" only if the page behind is really blocked.
  2. A name. Point aria-labelledby at the pop-up’s visible headline. “Dialog: Free shipping on orders over $50” tells the visitor what this is before they decide whether to read on.
  3. Readable content. If the headline, offer and terms are drawn into an image, a screen reader gets nothing unless the image has a text alternative that carries the same message (WCAG 1.1.1). The best fix is to keep the important words as real HTML text. If you must use an image of text, the alt text should state the offer itself — “10% off your first order with code WELCOME10, ends Sunday” — not “promo banner.”

Decorative images (a background photo, a confetti graphic) should have empty alt text, alt="", so they are skipped.

The close button deserves its own checklist

The close button is the single most important control in a marketing pop-up, because it’s the one most visitors use. A good one:

  1. Is a <button>, so it’s in the Tab order and works with Enter and Space.
  2. Has an accessible name. An icon-only button needs aria-label="Close" (or visually hidden text). A bare “✕” character may be read as “times” or “multiplication x,” and an icon image with alt="" gives it no name at all.
  3. Is big enough. WCAG 2.2 criterion 2.5.8 asks for pointer targets of at least 24×24 CSS pixels, unless an undersized target has enough space around it. Larger is kinder on phones.
  4. Is visible. The icon should reach at least 3:1 contrast against what’s behind it (1.4.11), and it shouldn’t sit partly off-screen on small viewports.
  5. Shows focus. Don’t remove the outline. If you restyle it, make the focused state clearly different.

Forms inside pop-ups

Email sign-up pop-ups are forms, and every form rule applies, inside a small box. The short version (our form UX guide goes deeper):

  1. Give every field a label. Placeholder text disappears as soon as someone types, and isn’t a reliable label. A visible <label> is best; at minimum, aria-label.
  2. Declare the input purpose. type="email" brings up the right keyboard on phones, and autocomplete="email" lets browsers offer the saved address (WCAG 1.3.5).
  3. Describe errors in text, next to the field, and connect them with aria-describedby. “Please enter your email address” is better than a red border alone (WCAG 3.3.1).
  4. Announce the result. Put the success or error message in a live region (for example role="status") so screen readers read it without the visitor having to hunt for it (WCAG 4.1.3).

Contrast, motion and timing

Body text needs a 4.5:1 contrast ratio against its background under WCAG 1.4.3 (large text has a lower threshold); text laid over a photo needs a solid or darkened panel behind it to stay readable at every point.

Keep entry animations short and simple, and respect the prefers-reduced-motion media query if you write your own CSS. Countdown timers are a special case: a ticking number is constantly changing content. Don’t put the timer itself in a live region, or a screen reader may try to announce every second. For when a countdown is appropriate at all, see Countdown Timer Pop-ups.

A minimal accessible pop-up with the native dialog element

If you build pop-ups yourself, start with <dialog> and showModal(). As MDN notes, a dialog opened this way makes the rest of the page inert, closes on Escape by default and is exposed with aria-modal="true". Here’s a bare-bones example; you would add your own styling and trigger logic.

<dialog id="offer" aria-labelledby="offer-title">
  <button type="button" class="close" aria-label="Close" autofocus>×</button>
  <h2 id="offer-title">Get 10% off your first order</h2>
  <p>Join our list and we'll email you a one-time code.</p>
  <form method="post" action="/subscribe">
    <label for="offer-email">Email address</label>
    <input id="offer-email" name="email" type="email"
           autocomplete="email" required aria-describedby="offer-msg">
    <button type="submit">Send my code</button>
    <p id="offer-msg" role="status"></p>
  </form>
</dialog>

<script>
  const dlg = document.getElementById('offer');
  let returnTo = null;
  function openOffer() {
    returnTo = document.activeElement;   // remember where focus was
    dlg.showModal();                     // inert background, Esc closes
  }
  dlg.querySelector('.close').addEventListener('click', () => dlg.close());
  dlg.addEventListener('close', () => {
    if (returnTo && document.contains(returnTo)) returnTo.focus();
  });
</script>

The autofocus on the close button follows MDN’s suggestion for dialogs where nothing needs more immediate interaction; move it to the email field if sign-up is the main point. The close event fires whether the visitor used the button or Escape, so focus is restored either way. And the success message would be written into the role="status" paragraph by your submit handler, so it gets announced.

Bars and floating banners are different

Not every pop-up is modal. An announcement bar across the top of the page, or a small floating banner in a corner, doesn’t block the page, so it shouldn’t trap focus or use aria-modal. Different rules matter instead:

  1. Don’t cover focused content. A sticky bar that hides the field or link a keyboard user just tabbed to fails WCAG 2.4.11. Leave space for it, or keep it short.
  2. Keep it reachable. Its links and close button should still be in a sensible Tab order.
  3. Don’t steal focus. A non-modal banner appearing shouldn’t yank focus away from what the visitor is doing.

For many messages a bar or floating banner is enough, and it’s easier to make accessible than a modal. Our free shipping banner guide compares the two formats.

Where marketingLABO banners stand today

marketingLABO shows pop-up banners on your site through one tracking tag, in three display styles: modal, floating and bar. We checked how those banners behave against the pattern above. Most of the keyboard and screen reader basics are now in place, including for banners you saved before the change; a few gaps remain, and you should know them before you choose a format.

AreaWhat marketingLABO banners do today
Close controlEvery banner has a close control (a “✕” or a close icon). Once a visitor closes a banner, it isn’t shown again during that browser tab’s session.
Close control — keyboardIt has role="button" and tabindex="0", so it can be reached with Tab, and Enter or Space closes the banner. It shows a visible focus outline. Remaining gap: it is a span with a button role, not a real <button> element.
Close control — nameIt has an accessible name: “Close” on English pages, “閉じる” on Japanese pages, based on the page’s language.
Close control — sizeThe editor offers a smaller and a larger close button. The smaller one is drawn at 18×18 px, but its clickable area is extended to at least 24×24 px, WCAG 2.2’s minimum; the larger one is 40×40 px.
Escape keyEscape closes a modal banner. It takes the same path as clicking the close button, so the banner stays dismissed for the rest of the tab’s session.
Dialog role and nameModal banners have role="dialog", aria-modal="true" and an accessible name taken from the banner name. Floating banners and bars are marked as named regions instead, without aria-modal.
FocusWhen a modal opens, focus moves to its close button; Tab and Shift+Tab stay inside the modal; on close, focus returns to the element that had it before. Floating banners and bars don’t take focus. Gap: the page behind a modal is not made inert, so a screen reader’s reading cursor can still move into it.
Image-only bannersThe image’s alt text is the banner name you enter in the dashboard. A descriptive name (“Free shipping over $50”) becomes useful alt text; an internal name (“Q4 test B”) does not.
Template banners (editor)The designed banner is published as a single image with clickable areas on top. The image’s alt text is now the banner name, but the headline and offer text themselves are still part of the image, so a screen reader hears only that name. Each clickable area gets a label from the element’s name in the editor or, failing that, the end of its link URL.
Email sign-up formThe email field is type="email", and the fields carry autocomplete values (email, family name, given name). Each field’s accessible name comes from its placeholder; there is still no visible label. Errors set aria-invalid, are linked with aria-describedby, and focus moves to the first invalid field. The success message appears inside the banner in a role="status" region instead of a browser alert. On pages whose language isn’t Japanese, the messages are in English.
MotionGap. Entry animations don’t check prefers-reduced-motion. If that matters to your visitors, choose no animation.
Exit intentExit-intent banners don’t manipulate the browser’s Back button or history.

Put simply: marketingLABO modal banners now follow the core of the APG modal dialog pattern — role and name, focus in, Tab kept inside, Escape, focus returned. What they don’t do yet is make the page behind inert, use a native button for close, or expose the words inside template images as text.

Getting the most out of marketingLABO banners

A few settings help with the gaps that remain:

  1. Prefer bar or floating banners for important messages. They don’t block the page or take focus. Reserve modals for messages that are genuinely optional.
  2. Avoid “show immediately” modals. Because the page behind isn’t inert, a screen reader user can wander behind the modal without noticing it. Use a scroll depth or time on page trigger, or exit intent, so the visitor has already seen the page.
  3. Choose the larger close button and a color with strong contrast against the banner. The smaller one is easy to tap now, but still hard to see.
  4. Write descriptive banner names. The name is the dialog’s name and the image’s alt text, for image-only and template banners alike. State the offer, not the campaign label.
  5. Never put an offer only in a banner. Repeat it in real page text — the cart page, the shipping policy, the product page — so nobody depends on the pop-up to learn it.
  6. Name the link areas in template banners so their labels make sense on their own (“Shop the sale”), instead of falling back to a piece of the URL.
  7. Write clear placeholders and keep forms short. The placeholder becomes the field’s name, so “Email address” works better than “you@example.com”. Ask for email only.

Banner limits depend on your plan: Free includes one pop-up banner, Light three, and Standard has no limit. See pricing.

A ten-minute test for any pop-up

Run this on your own store, on desktop and on a phone:

  1. Unplug the mouse. Load the page and trigger the pop-up (for a time or scroll trigger, wait or scroll with the keyboard). Without touching the mouse or trackpad, can you tell where focus is?
  2. Tab through it. Does the next Tab land inside the pop-up? Can you reach every control, including close? Does focus stay inside a modal, or slip out to the page behind?
  3. Press Escape. Does the pop-up close? Where is focus afterwards?
  4. Submit the form wrong. Leave the email field empty and submit. Is the error shown in words? Then submit correctly — can you tell it worked without looking?
  5. Turn on a screen reader — VoiceOver on Mac or iPhone, TalkBack on Android, NVDA or Narrator on Windows. Trigger the pop-up. Is it announced? Does the close button have a name? Is the offer itself read out?
  6. Check contrast of the headline, fine print and close icon with a contrast checker in your browser’s developer tools.

FAQ

Is a focus trap bad for accessibility?

Not inside a modal dialog. The APG pattern expects Tab to loop within the dialog. What WCAG 2.1.2 forbids is a trap with no way out. As long as Escape or a reachable close button lets the visitor leave, keeping focus inside the modal is correct.

Should I use role="dialog" or role="alertdialog"?

Use dialog for marketing pop-ups. The APG describes alertdialog as a special case for brief, important messages that need the user’s attention, such as confirming a destructive action. A coupon offer isn’t that.

Are accessible pop-ups worse for conversion?

We don’t know of a reliable public study either way. What’s clear is that a visitor who can’t read or close a pop-up can’t convert through it.

Is this legal advice?

No. Accessibility obligations depend on where you sell and to whom. This guide is about meeting the W3C pattern and WCAG 2.2 in practice; ask a qualified advisor about your legal requirements.

Want to see how visitors interact with your pages first? Create a free account, add the tag, and use heatmaps to check whether people scroll far enough to see your offer before you decide to put it in a pop-up at all.

Sources

  1. W3C WAI, ARIA Authoring Practices Guide, “Dialog (Modal) Pattern” (accessed October 12, 2026): https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/
  2. W3C, Web Content Accessibility Guidelines (WCAG) 2.2, W3C Recommendation, December 12, 2024 (accessed October 12, 2026): https://www.w3.org/TR/WCAG22/
  3. MDN Web Docs, “<dialog>: The Dialog element” (accessed October 12, 2026): https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/dialog

Start free — no credit card needed

Sign up free