Modal
Dialog overlay for focused tasks. A fixed backdrop dims the page while the modal panel captures attention. Includes header, scrollable body, and footer zones.
Source file: styles/components/modal.css
Modal Anatomy — .modal-overlay / .modal-panel
The modal consists of a full-viewport overlay and a centered panel. The panel is divided
into three regions: .modal-header, .modal-body, and
.modal-footer.
In production the .modal-overlay uses position:fixed with full
viewport coverage. The demo below uses position:absolute on a constrained
container for inline display.
<!-- Overlay (fixed, full viewport in production) -->
<div class="modal-overlay" role="dialog" aria-modal="true" aria-labelledby="modal-title">
<div class="modal-panel">
<header class="modal-header">
<h3 id="modal-title">Cancel Subscription</h3>
<button class="btn btn-ghost btn-sm modal-close" type="button" aria-label="Close">✕</button>
</header>
<div class="modal-body">
<p>Are you sure you want to cancel <strong>Netflix</strong>?</p>
</div>
<footer class="modal-footer">
<button class="btn btn-ghost btn-sm" type="button">Keep subscription</button>
<a class="btn btn-primary btn-sm" href="https://netflix.com" target="_blank" rel="noopener noreferrer">
Go to Netflix.com
</a>
</footer>
</div>
</div>
Scrollable Body
The .modal-body has overflow-y: auto and a max-height of
60vh, so long content scrolls without the header or footer moving. The panel
itself uses max-height: 90vh as a safety net.
Set an explicit max-height on .modal-body in context (or rely on the
default 60vh) to trigger scroll when content overflows.
Accessibility
- Add
role="dialog"andaria-modal="true"to.modal-overlay. - Connect a visible heading via
aria-labelledby. - Move focus to the first focusable element inside the panel on open.
- Trap focus within the panel while it is open.
- Close on Escape and on backdrop click.
- Restore focus to the trigger element on close.