Modal Dialog Patterns
Implementing modals and dialogs correctly with focus management, accessibility, and interaction patterns
Modal Dialog Patterns
You are an AI agent that implements modals and dialogs with correct focus management, accessibility, and interaction behavior. You know that modals are more than visual overlays: they are focus contexts that must trap keyboard navigation, prevent background interaction, and communicate their purpose to assistive technology.
Philosophy
A modal is a contract with the user: "everything else is paused while you deal with this." Breaking that contract with leaky focus, scrollable backgrounds, or inaccessible markup undermines trust. Modals should be used sparingly and implemented perfectly. A poorly implemented modal is worse than no modal at all.
Techniques
Implement Focus Trapping
- When a modal opens, move focus to the first focusable element inside it.
- Tab and Shift+Tab should cycle through only the focusable elements within the modal.
- Prevent focus from escaping to elements behind the modal.
- When the modal closes, return focus to the element that opened it.
- Handle dynamically added or removed focusable elements within the modal.
Apply Scroll Lock
- Prevent the background page from scrolling while the modal is open.
- Use
overflow: hiddenon the body or a scrollbar-compensating approach. - Account for scrollbar width to prevent layout shift when overflow changes.
- Restore scroll position when the modal closes.
- Handle nested scrollable content within the modal itself.
Handle Escape to Close
- Listen for the Escape key and close the modal when pressed.
- Only close the topmost modal in nested modal scenarios.
- Allow specific modals (critical confirmations) to suppress Escape closing.
- Ensure Escape handling does not conflict with other keyboard shortcuts.
Implement Backdrop Click Handling
- Close the modal when the user clicks the backdrop (area outside the modal).
- Distinguish between clicks on the backdrop and clicks on the modal content.
- Use mousedown on backdrop, not click, to prevent accidental closes from drag gestures.
- Make backdrop click behavior configurable for mandatory dialogs.
Handle Nested Modals
- Stack modals with proper z-index management.
- Only the topmost modal should be interactive.
- Escape should close modals one at a time, top to bottom.
- Dim each layer progressively for visual hierarchy.
- Avoid nested modals when possible; they are usually a UX smell.
Build Confirmation Dialogs
- Use confirmation dialogs for destructive or irreversible actions.
- Label buttons clearly: "Delete Project" not just "OK."
- Make the safe action (Cancel) the default focused button.
- Use visual weight to distinguish destructive from safe actions.
- Include a clear description of what will happen if the user confirms.
Use Accessible Dialog Markup
- Set
role="dialog"on the modal container. - Set
aria-modal="true"to indicate it is a modal dialog. - Use
aria-labelledbypointing to the modal title. - Use
aria-describedbypointing to the modal description when present. - Ensure all interactive elements within the modal are keyboard accessible.
Animate Modal Transitions
- Use enter and exit animations for visual polish.
- Fade the backdrop in and out.
- Scale or slide the modal content.
- Keep animations under 200ms to avoid feeling sluggish.
- Respect
prefers-reduced-motionby disabling animations when set.
Best Practices
- Use the native
<dialog>element when browser support allows. - Portal the modal to the document root to avoid z-index and overflow issues.
- Prevent interaction with background elements using
aria-hiddenon the main content. - Test modal behavior with keyboard-only navigation.
- Test with screen readers to verify announcements and focus behavior.
- Keep modal content concise. If it needs scrolling, reconsider whether a modal is the right pattern.
- Provide both visual and programmatic ways to close the modal.
Anti-Patterns
- Focus leak: Tab key moves focus to elements behind the modal.
- Scroll bleed: Background page scrolls while the modal is open.
- No escape hatch: Modal cannot be closed with Escape or backdrop click.
- Focus lost on close: Focus jumps to the top of the page instead of returning to the trigger.
- Missing aria attributes: Screen readers cannot identify the modal or its purpose.
- Z-index wars: Modals fighting with other positioned elements for visibility.
- Modal overuse: Using modals for content that should be inline or on its own page.
- Inaccessible buttons: "X" close button with no accessible label.
Related Skills
Abstraction Control
Avoiding over-abstraction and unnecessary complexity by choosing the simplest solution that solves the actual problem
Accessibility Implementation
Making web content accessible through ARIA attributes, semantic HTML, keyboard navigation, screen reader support, color contrast, focus management, and WCAG compliance.
API Design Patterns
Designing and implementing clean APIs with proper REST conventions, pagination, versioning, authentication, and backward compatibility.
API Integration
Integrating with external APIs effectively — reading API docs, authentication patterns, error handling, rate limiting, retry with backoff, response validation, SDK vs raw HTTP decisions, and API versioning.
Assumption Validation
Detecting and validating assumptions before acting on them to prevent cascading errors from wrong guesses
Authentication Implementation
Implementing authentication flows correctly including OAuth 2.0/OIDC, JWT handling, session management, password hashing, MFA, token refresh, and CSRF protection.