A modal sits on top of the page and keeps the user there until they finish what it asks or close it. Everything underneath stays visible but stops taking input. Teams use modals for confirmations, short forms and media previews, and they build them with the HTML dialog element or a component library.
Apple’s Human Interface Guidelines make a point that’s easy to miss. In iOS and iPadOS, one sheet component can be modal or nonmodal, so the name of a component tells you nothing about whether the page underneath stays usable. “Modal” is about behavior.
What Is a Modal?
Whatever it looks like, a modal holds the user in one focused task until they complete it or dismiss it. The page below keeps showing but doesn’t respond.
People say modal window, modal dialog, dialog box or just pop-up, and the terms get mixed up constantly. Of all the UI components, this one exists to interrupt.
The word describes the blocking behavior, not the visual appearance. A dialog that blocks its parent content is modal. One that doesn’t is nonmodal.
Delete confirmations and unsaved-changes prompts are the textbook cases. A photo opened over a gallery behaves the same way.
Nielsen Norman Group traces the original use to Microsoft PowerPoint, where modal dialogs stopped irreversible slips such as quitting without saving. The same source says the pattern later drifted into attention-grabbing prompts, which is where most of the trouble started.
What a Modal Blocks While It Is Open

Clicks on background buttons, links and fields do nothing. Tab and Shift+Tab loop inside the modal and never reach the page, and screen readers treat everything outside it as unavailable. The only way back to the page is to finish the task or close the modal.
The WAI-ARIA Authoring Practices call the windows under a modal dialog inert. Most non-modal dialogs let keyboard focus move out. A modal doesn’t, not without closing.
The background normally stays in view, dimmed. That tells sighted users the page is paused, not gone.
Each appearance costs some user experience, so whatever is inside had better be worth the interruption.
Carbon Design System describes what happens when it isn’t. Users who keep getting dialogs about non-workflow tasks start dismissing them unread, and eventually they rush the critical ones too.
Modal Anatomy and Ways to Close It

Carbon splits the visible window into a header, a body and a footer, with a dimmed layer behind all of it.
Core parts of a modal
- The container, which is the box holding everything
- An overlay (also called a backdrop or scrim) that dims the page
- A title, kept to a brief verb phrase that names the task
- The body, where the content or form sits
- Action buttons in the footer
- A close control, usually an X in the corner, that exits without submitting anything
Button labels get less attention than they deserve. Carbon wants specific verbs such as Add, Delete and Save and says to skip vague ones like Done or OK.
Dismissal methods and when each fits
The closedby attribute on the HTML dialog element handles dismissal. It accepts none, closerequest or any, and MDN’s compatibility data lists Chrome and Edge 134 and Firefox 141 as the first versions to support it.
With any, a click outside closes the dialog. Closerequest limits that to Esc and the platform’s back or dismiss gesture. None hands the whole job to your own code.
Always include a close button. Apple’s guidance adds that a visible dismiss button keeps the view usable with assistive technologies when gestures aren’t an option.
Escape is the keyboard way out, and the Authoring Practices list it as the key that closes a dialog. Clicking the backdrop works well for read-only content and badly when the modal holds typed input. Action buttons are the only exit that records a decision, whether that’s Save, Delete or Cancel.
Apple also says modal views should ask for confirmation before closing if closing would lose data.
Types of Modals
Interfaces mostly use some version of the modal dialog, the alert dialog, the lightbox, the full-screen modal or the bottom sheet. What separates them is how much screen they take and how urgent the message is.
- The plain modal dialog handles short input or a confirmation. Carbon lists passive, transactional, danger, acknowledgment and progress variants, and keeps danger for destructive or irreversible actions.
- An alert dialog interrupts to deliver an important message and get a response (WAI-ARIA Authoring Practices). It’s a modal dialog with a narrower job, and action confirmations and error acknowledgments are the standard cases.
- Lightboxes put a photo or video preview over a dimmed page. The user starts one by clicking a thumbnail.
- Apple’s Human Interface Guidelines point to full-screen modals for videos, photos and camera views, and Material Design 3 offers basic and full-screen dialogs side by side.
- Mobile gets the bottom sheet. Material’s modal bottom sheet replaces inline menus and simple dialogs, blocks the rest of the screen, and closes with a tap outside or a downward drag.
Apple draws a complexity line for sheets too. Complex or prolonged flows call for an alternative.
Carbon puts it from the other direction. If the content needs more room than the large modal size gives it, it belongs on its own page.
Modal vs Popup, Popover, Drawer and Toast
Modals block the page and demand a response. Popovers, toasts and standard drawers leave the page usable.
| Pattern | Blocks the page | Needs a response | Typical use |
|---|---|---|---|
| Modal | Yes | Yes | Confirmation, short required input |
| Non-modal dialog | No | No | Optional task such as find and replace |
| Popover | No | No | Menus, short contextual info |
| Drawer | Only in modal form | Only in modal form | Navigation, filters, side panels |
| Toast | No | No | Brief system feedback |
Every modal is a dialog. The reverse isn’t true. A nonmodal dialog does a similar job without blocking anything, and Gmail’s compose window is the usual example.
“Popup” is the loose everyday word. A modal is a popup that blocks the page, so the terms overlap but they aren’t interchangeable.
The Popover API is non-modal by definition, according to the Open UI explainer, so a dialog that has to be modal should use the dialog element. Auto popovers close on an outside click or Esc. Manual ones stay open until code closes them (MDN).
A drawer slides in from an edge and can go either way. Material Design splits bottom sheets into standard and modal variants, and side sheets get the same split. The name alone won’t tell you whether the page stays usable.
A toast notification reports something that already happened. Carbon reserves it for system-generated messages that don’t follow from a user action. A background sync result fits that. A delete confirmation does follow from an action, so it goes in a modal.
When to Use a Modal
Reach for a modal when the user has to decide or provide something before anything else can happen, and the whole task fits in one short window. Work that can wait hasn’t earned the interruption.
Nielsen Norman Group and Carbon Design System phrase their guidance differently but end up in the same places. An urgent warning that stops a critical error before the user commits to it qualifies. So does blocking input, like a required field, a missing permission or a selection the process can’t continue without. Confirming a decision counts too, whether it’s a delete, a payment or anything else that’s hard to undo. Nielsen Norman Group also allows a modal when the answer lessens the user’s work.
According to Nielsen Norman Group, Etsy uses a modal whenever a task needs further steps before the user can continue, and wizards are the common case.
Decision test
Start with who triggered it. Either the user opened it or it’s a direct result of what they just did. Then check whether the task can be finished with the information inside the modal. Both checks come from Carbon’s guidance on user-initiated, self-contained dialogs.
Cost settles the borderline cases. If skipping the modal costs more than interrupting would, it passes. A modal needs a yes on every one of these.
For irreversible actions, put initial focus on the least destructive button. The WAI-ARIA Authoring Practices recommend this for financial transactions and other hard-to-undo steps.
When a Modal Is the Wrong Choice
Noncritical tasks and long flows don’t belong in a modal, and a prompt the user never asked for is worse. Nielsen Norman Group calls modals problematic once they carry noncritical activity, since they demand immediate attention and pull people away from what they were doing.
Poor-fit use cases
- System-generated surveys, such as a Net Promoter Score prompt (Carbon Design System)
- Checkout and other high-stakes flows (UMass Design System, building on Nielsen Norman Group)
- Decisions that need information the modal cannot show (same source)
- Content that needs a full page, since Carbon states a modal is not an alternative to one
If the user has to leave the modal to finish the job, the job never belonged in one.
Stacked and auto-triggered modals
Carbon’s design position is that one modal should never trigger another, and that a task needing a confirmation modal shouldn’t live in a modal at all. Apple’s guidelines warn that several modal views at once force people to hold more than one previous context in their heads.
Implementation points the other way. MDN documents that showModal() displays the dialog over any other dialogs already present, and Stream merged stackable modal support into its Chat React SDK in June 2026 so a channel details modal could open a “Delete chat” confirmation on top (GitHub pull request).
Both positions are on the record and they conflict. My practical line is one confirmation layer over a task modal, and never a third.
Auto-triggered modals cause the rest of the damage. Carbon limits dialogs to moments the user initiated, which rules out opening one the user didn’t trigger.
Modals on mobile landing pages
Google’s ranking signal against intrusive interstitials on mobile took effect on January 10, 2017 (Google Search Central announcement, 2016).
It targets pop-ups that cover the main content after a searcher taps through. Search Engine Land reported in 2017 that pages deeper in the click path are not evaluated, so the exposure sits on the landing page itself.
Google’s announcement exempts interstitials that respond to a legal obligation, like cookie use or age verification. Login dialogs on sites where content isn’t publicly indexable, such as private email or paywalled content, are exempt as well, and so are banners that take a reasonable amount of screen space and dismiss easily.
The signal describes pop-ups that hinder access when the page loads, so a modal opened by a user tap sits outside it. These details reflect the 2017 rollout reports, so check Google’s current Search Central documentation for later changes.
Alternatives to a modal
| Situation | Use instead |
|---|---|
| Long or multi-step task | A dedicated page |
| Form fields, dropdowns, expandable sections | Inline content on the page |
| Optional or reference information | A non-modal dialog |
| Result of a background process | A toast or banner |
Eleken’s modal guide notes that forms, dropdowns and expandable sections usually work better directly on the page. When a flow has stages, a stepper component on its own page keeps the user oriented.
How to Make a Modal Accessible
Screen readers need a dialog or alertdialog role, aria-modal set to true and an accessible name to describe a modal correctly. Focus management is the other half. Get it wrong and keyboard users lose their place.
Roles, names and aria-modal
The container carries role dialog, or alertdialog for urgent messages, along with an accessible name. In the WAI-ARIA Authoring Practices, the ARIA markup points aria-labelledby at the visible title (aria-label when there isn’t one) and sets aria-modal to true.
The native dialog element already has the dialog role, and WebKit’s documentation says a modal one behaves like aria-modal=”true”.
Go easy on aria-modal, though. The Authoring Practices say to mark a dialog modal only when code blocks all interaction outside it and the styling visually obscures the page. Support arrived with ARIA 1.1 and still varies across screen readers.
The focus sequence
- Save a reference to the control that opened the modal.
- Move focus inside. Where it lands depends on the content. A form gets the first input, irreversible actions get the least destructive button, and long text that would scroll out of view gets a static title with tabindex=”-1″. Never make the dialog container itself focusable.
- Keep Tab and Shift+Tab inside. From the last control, Tab wraps to the first, and Shift+Tab from the first wraps to the last.
- Close on Escape, and keep a visible close button for everyone else.
- Return focus to the saved control. If it no longer exists, send focus to the next logical element in the workflow.
WCAG touches this sequence in criteria 2.1.2 No Keyboard Trap (Level A), 2.4.3 Focus Order (Level A) and 2.4.7 Focus Visible (Level AA). The trap inside a modal is deliberate, and 2.1.2 only asks that a keyboard exit exists, which is Escape or the close button.
Alert dialog initial focus: a documented disagreement
Sources don’t agree on where focus lands when an alert dialog opens. The ARIA 1.1 specification says to focus an active element such as an OK button or a form field. The Authoring Practices pattern of the time put focus on the message text (role document, tabindex 0), according to Deque.
Deque’s 2016 testing found the Authoring Practices structure worked for NVDA but performed poorly with VoiceOver, so Deque published a variant that focuses the first button.
That test is a decade old. Retest on current NVDA and VoiceOver builds before copying either pattern, and run the result through a web accessibility checklist before release.
Building a Modal with the HTML Dialog Element
Call showModal() on a dialog element and the browser puts it in the top layer with a ::backdrop, blocks interaction outside it and makes the rest of the document inert (MDN). Calling show() or setting the open attribute gets you a non-modal dialog instead.
Baseline lists showModal() as widely available, with support in every major browser since March 2022 (MDN). The versions behind that:
- Chrome 37 and Edge 79
- Firefox 98
- Safari and iOS Safari 15.4
Anything older than those needs a fallback or a library.
Native dialog behavior
MDN notes that the native element provides usability and accessibility features a hand-built modal has to replicate. That goes for CSS-only modals as much as for script-heavy widgets.
Here’s a minimal delete confirmation. Cancel gets focus first because the action is destructive.
<button id="open">Delete project</button>
<dialog id="confirm" aria-labelledby="confirm-title">
<h2 id="confirm-title">Delete this project?</h2>
<form method="dialog">
<button value="cancel" autofocus>Cancel</button>
<button value="delete">Delete</button>
</form>
</dialog>
<script>
const dlg = document.getElementById("confirm");
document.getElementById("open")
.addEventListener("click", () => dlg.showModal());
</script>- MDN recommends autofocus on whatever users act on first, or on the close button when nothing else qualifies. OpenReplay reports autofocus is unreliable in some desktop browsers, so set focus in script right after showModal() when initial focus matters.
- Before closedby, native modals ignored backdrop clicks. The usual workaround checks whether the click target is the dialog element itself, because a click on the ::backdrop registers there (OpenReplay).
- Only the document that contains the dialog is blocked. A dialog inside an iframe leaves the parent page interactive (MDN).
- Submitting a form with method=”dialog” closes the dialog and fires a close event, and the dialog’s returnValue records the outcome, so confirm and cancel buttons need no extra script.
- The close() method returns focus to the element that opened the dialog, per OpenReplay.
- The top layer paints above all other page content (Open UI explainer), so z-index battles disappear. The ::backdrop pseudo-element styles the dimmed layer and appears only for modal dialogs (WebKit).
Native dialog or a library component
Go native unless a requirement rules it out. Libraries add things the native element’s documentation doesn’t list, such as scroll locking.
Radix UI Dialog brings a focus trap, Esc to close and screen reader announcements through Title and Description parts, with the content underneath rendered inert (Radix documentation). It only works with React.
Headless UI Dialog locks scroll, hides the rest of the app from screen readers and closes on an outside click or Escape. It’s renderless, so the markup and styles are all yours.
Bootstrap ships a styled modal with ready-made classes. Its animation honors prefers-reduced-motion, and its docs advise an h1 for the modal title because a modal is its own context.
Projects already on Bootstrap can keep the Bootstrap modal. New builds lose little by starting with the native element, and I’d go native on anything new.
Modal FAQ
How do you stop the page from scrolling behind a modal?
Set overflow: hidden on the body while the modal is open, and remove it on close.
The native dialog element’s documented behavior covers focus, inertness, the backdrop and Esc, but not scroll locking. Headless UI locks scroll for you.
What is the simplest way to center a modal with CSS?
Open the dialog with showModal(). The browser fixes it in the top layer and centers it with its default styles, so no extra CSS is needed.
For a hand-built modal, make the overlay fixed and full-screen, then set display: grid and place-items: center on it.
Can a modal hold a form?

Yes, as long as the form is short. Carbon Design System describes modals as suited to brief, infrequent tasks such as editing.
A long form belongs on its own page. When a modal body does run long, only the body scrolls while the header and footer stay fixed.
How wide should a modal be on mobile?
Most of the screen width. Carbon sizes modals as a percentage of the browser, and that percentage grows as the browser shrinks.
Content should never scroll horizontally. If it doesn’t fit, step up a modal size or switch to a full-screen modal or bottom sheet.
How to Test a Modal Before Release
Run it with keyboard only first, then a screen reader, then a phone-sized viewport. Each pass depends on the one before it, so the order isn’t arbitrary.
The keyboard pass means opening the modal, tabbing through it, pressing Esc and confirming that focus returns. NVDA and VoiceOver come next, to check the name, the role and the focus announcements. The phone viewport covers layout, scrolling and the close control.
A screen reader pass on a modal with broken focus ends up testing the wrong element, which is why the keyboard pass goes first. The phone pass can wait until the end, since it only checks presentation and the earlier passes have already sorted out behavior.
All of this takes time. Run every pass on modals that ship new focus logic, and repeat only the keyboard pass after copy changes.
This sequence reflects the position verified on October 26, 2026. Rerun the screen reader pass whenever a library or browser update touches dialog focus handling, and apply the same keyboard-first order to other accessible UI components.
- How to Insert Image in Figma With Ease - November 3, 2026
- How to Download Figma Files Fast and Free - October 30, 2026
- Figma Keyboard Shortcuts That Will 10x Your Speed - October 25, 2026


