MODALLY

It's your trusty nested modals ally.

Try me! Video? Real Video? Image? ↓

Modally

Your trusty nested modal ally — simple, framework-agnostic modal dialogs with accessible focus management.

Modally turns any hidden element into an accessible modal dialog. It follows the WAI-ARIA Authoring Practices dialog pattern: focus moves into the dialog on open, is trapped inside while open, and returns to the trigger on close. Esc closes the top-most modal.

Quick start

Give your content an id and a link that targets it. Modally wraps the content in an accessible dialog for you.

<div id="hello" hidden><h1>Hello world!</h1></div>
<a href="#hello" target="_modal">Open</a>
const modally = new Modally()
modally.add('hello')

Try the demo modal

Custom element (no build, no JS wiring)

Prefer HTML? Use the <modally-dialog> custom element. It uses no shadow DOM, so your own CSS styles the content directly. Every attribute becomes a modal option.

<modally-dialog id="greeting" max-width="600">
  <h1>Hey there!</h1>
  <p>Styled by your own stylesheet — no piercing needed.</p>
</modally-dialog>
<a href="#greeting" target="_modal">Open</a>

Try the custom element

Nested modals

Open a modal from inside another — Modally tracks the stack automatically and blurs the parent. No extra code.

<a href="#child" target="_modal">Open a nested modal</a>

Video embeds

Pass video: true and a data-video URL. YouTube, Vimeo and raw video files are detected and embedded automatically, with optional autoplay.

modally.add('video-modal', { video: true })
<a href="#video-modal" target="_modal"
   data-video="https://www.youtube.com/watch?v=u9QJo5fBADE">Watch</a>

Try a video modal

Image lightbox

Pass image: true and a data-image URL to open a responsive lightbox.

modally.add('image-modal', { image: true })
<a href="#image-modal" target="_modal"
   data-image="/photo.jpg" data-width="800" data-height="1192">View</a>

Options

OptionDefaultDescription
maxWidth'none'Max width of the modal window (px).
disableScrolltrueBlock body scroll while open.
verticalAlign'middle'middle, top or bottom.
closeOthersfalseClose other open modals on open.
video / imagefalseEnable video embed / image lightbox.

See the README for the full list. Options can also be set via modally-<option> attributes on the element.

Events

Modally dispatches lifecycle events on document: modally:open, modally:opened, modally:close, modally:closed and modally:added — each with the modal instance in event.detail.

document.addEventListener('modally:opened', (e) => {
  console.log(e.detail.id)
})
Tested with BrowserStack