Appearance
Accessibility
Modal dialogs are one of the easiest components to get wrong. NXPopup is built on the native HTML <dialog> element specifically because the browser then handles the hardest parts correctly.
What the native dialog provides
Opening with showModal() gives the following behaviour from the browser itself, rather than from hand-written JavaScript:
- Focus containment. Tab and Shift+Tab cycle within the dialog and cannot reach the page behind it.
- Inert background. Content outside the dialog is not reachable by keyboard, pointer, or assistive technology.
- Escape to close. Handled natively; NXPopup intercepts it only to run the closing animation.
- Top-layer rendering. The dialog is painted above all page content regardless of
z-index.
Keyboard behaviour
| Key | Result |
|---|---|
| Tab / Shift+Tab | Cycles through the close button and CTA, staying inside the dialog. |
| Escape | Closes the popup, with the exit animation. |
| Enter / Space | Activates the focused control. |
Focus on open
Focus moves to the popup frame, which is a non-interactive container with tabindex="-1". This is deliberate:
- The dialog is announced to screen readers.
- No button is pre-armed, so an immediate Enter press cannot accidentally follow the CTA.
- The first Tab press moves to the close button and shows a visible focus ring, as normal.
Focus on close
Focus returns to whatever the visitor was on before the popup opened, so keyboard and screen-reader users are not dropped back at the top of the page.
Screen reader labelling
The dialog is labelled from the popup's own content:
- With a title,
aria-labelledbypoints at the heading. - With no title, a translated
aria-labelis used instead, so the dialog always has an accessible name. - With body content,
aria-describedbypoints at it. With no body, the attribute is omitted rather than left dangling.
The close button carries a translated aria-label, and its icon is marked aria-hidden.
Reduced motion
When a visitor has prefers-reduced-motion: reduce set, the open and close transitions are disabled and the popup appears and disappears immediately. The script skips waiting for a transition in that case, so closing stays instant.
Writing accessible popup content
The module handles the mechanics; the content is yours:
- Give every popup a title. It becomes the dialog's accessible name.
- Write a descriptive CTA. "Learn More" is acceptable in context; "Click here" is not.
- Check colour contrast. The colour settings let you choose anything, including combinations that fail WCAG AA. The default palette places white text on a dark image; if you change the background, verify the title, body, and button text still meet 4.5:1.
- Do not rely on the popup alone. Anything essential should also exist on the page, since visitors can dismiss the popup.
Choosing considerate triggers
Accessibility includes not being hostile:
- Avoid a
0ms delay on content pages — it interrupts before the visitor has oriented. - Use the page-view gate so first-time visitors are not immediately interrupted.
- Keep Dismiss on Backdrop Click off (the default) so an accidental click is not treated as a decision.
- Set a realistic Dismissal Period. Re-prompting a visitor who said no is the most common complaint about popups.
Standards notes
The implementation targets WCAG 2.1 AA for the component itself, including 2.1.2 No Keyboard Trap (via the native dialog's managed focus), 2.4.3 Focus Order, and 2.4.7 Focus Visible.
Two criteria depend on your configuration rather than the module: 1.4.3 Contrast is determined by the colours you choose, and 2.2.1 Timing Adjustable by whether your popup contains time-limited content. NXPopup never auto-closes, so the visitor always controls dismissal.