Skip to main content

Modal

A dialog overlay that focuses user attention on a task or decision. Use when an action requires explicit user confirmation. Don't use for non-critical information that can be shown inline — use Alert instead.

OverviewStyleAccessibility

Description

Anatomy

PartRequired?Notes
Backdrop Required Semi-transparent overlay behind the modal. Clicking it dismisses the modal unless the action is destructive or data entry is in progress.
Header Required Contains the modal title, and a status icon to its left in the status variants. Must be linked to the dialog via aria-labelledby.
Header actions Optional Extra icon buttons in the header, beside the close button (for example an open-in-new-window link).
Body content Required The main content. Keep it focused — modals are not a canvas for complex layouts.
Close button Required × button at the right of the header. Always present unless the action is a required confirmation with no dismissal path.
Secondary action Conditional Cancel, Go back, or an alternative action. Omit when the close button already serves this role.
Primary action Required The main call to action. Use a destructive button style for irreversible actions.

Variants

Usage guidelines

Do / Don't

Do

Write modal titles as plain questions or statements: "Delete this project?" or "Export stakeholder data". Not "Confirmation Required".

Don't

Don't nest modals. If a modal action opens another modal, the flow needs redesigning.

Do

For destructive actions, make the consequence explicit: "This will permanently delete 47 responses and cannot be undone."

Don't

Don't make "Cancel" the primary button. The primary action should always be the most likely next step.

Layout & Spacing

Modals are centred horizontally and vertically in the viewport. They have a maximum width and scroll internally when content overflows — the backdrop and modal chrome stay fixed.

Element Spec
Width 480 / 640 / 800px (S / M / L), or fullscreen; 90vw on small screens. --orbit-modal-size-*-width
Max height 85vh — body scrolls internally beyond this
Header padding 12px top, 24px left, 12px right (beside the close button); 8px between a status icon and the title. --orbit-modal-header-*
Body padding 24px on all sides. --orbit-modal-body-padding
Footer padding 24px left, right and bottom; 8px between buttons. --orbit-modal-footer-padding, -actions-gap
Border radius 12px (none when fullscreen). --orbit-modal-radius
Shadow Large elevation shadow. --orbit-modal-shadow-*
Backdrop colour --orbit-modal-scrim
Title 20px heading font (Lora), medium weight
Body text 16px, regular weight

Component tokens

Modal and Notification Modal share one set of framework-neutral CSS variables. Notification Modal is the status variants (danger, warning, success, info), which add a status icon colour; the confirm button comes from Button's tokens.

Token What it sets
--orbit-modal-background, -radius, -scrim Surface, corner radius (overlay radius) and the backdrop colour.
`--orbit-modal-shadow-{offset-x offset-y
`--orbit-modal-size-{s m
`--orbit-modal-header-{padding-block padding-inline-start
`--orbit-modal-title-{color font-size
`--orbit-modal-body-{padding gap
`--orbit-modal-footer-{padding gap
`--orbit-modal-{danger warning
Element Token
Background --orbit-modal-background
Backdrop --orbit-modal-scrim
Title text --orbit-modal-title-color, --orbit-modal-title-font-size, --orbit-modal-title-font-weight
Body text --orbit-modal-body-color, --orbit-modal-body-font-size

Engineering notes

  • The native <dialog> element traps focus automatically when opened with showModal(). Custom implementations must implement a focus trap manually — focus should cycle through interactive elements within the modal and not reach page content behind it.
  • Always return focus to the element that triggered the modal on close. Without this, keyboard users lose their position in the page.
  • Don't use display: none to hide modals — use the hidden attribute or the dialog element's open state so screen readers don't read hidden content.
  • Avoid opening modals on page load. They interrupt users before they have context and are a common cause of accessibility failures in form-heavy applications.

Keyboard interaction

KeyAction
Tab Moves focus forward through interactive elements within the modal. Focus is trapped — it does not leave the modal.
Shift + Tab Moves focus backward through interactive elements within the modal.
Escape Closes the modal and returns focus to the triggering element. Always implement this unless the modal requires a mandatory decision.
Enter or Space Activates the focused button.

Why it matters

Focus management is the most commonly failed accessibility requirement in modals. When a modal opens, focus must move into it — otherwise keyboard and screen reader users are stranded on the page behind it. When it closes, focus must return to the trigger — otherwise users lose their place. Both are required for a modal to be genuinely accessible.

ARIA

Role or attributeWhen to useExample
role="dialog" Applied to the modal container. Identifies the element as a dialog. The native <dialog> element provides this implicitly. <div role="dialog" aria-modal="true" aria-labelledby="modal-title">
aria-modal="true" Applied to the modal container. Tells screen readers that content outside the modal is inert. Required on custom implementations. <div role="dialog" aria-modal="true">
aria-labelledby Applied to the modal container. Points to the modal's title element by ID. Ensures the modal title is announced when it receives focus. <div role="dialog" aria-labelledby="modal-title"><h2 id="modal-title">Delete project</h2>
aria-describedby Applied to the modal container. Optional. Points to the body text when a brief description should be announced alongside the title. <div role="dialog" aria-describedby="modal-desc"><p id="modal-desc">This action cannot be undone.</p>

How to apply it

When a modal opens, move focus to the modal container or to the first interactive element inside it — whichever gives the most useful context. For confirmation modals, focusing the container first means the title and description are announced before anything is activated. For form modals, focusing the first input is often more efficient.

Things to avoid

  • Don't allow focus to leave the modal while it's open. Page content must not be reachable via Tab.
  • Don't remove the modal from the DOM while it's open with animation — this can confuse screen readers. Animate out, then remove.
  • Don't use role="alertdialog" unless the modal is communicating a critical error that demands immediate attention. For confirmations and forms, role="dialog" is correct.
  • Don't auto-close modals on a timer. Users may need more time to read or act.

Was this page helpful?

Updated 2 October 2026