SiteDNA
Back to Blog

Accessible Modals and Dialogs: Focus Trapping Done Right

Modals are accessibility nightmares when done wrong. Learn how to build dialogs that work for everyone.

Accessible Modals and Dialogs: Focus Trapping Done Right

Modal dialogs are one of the trickiest components to make accessible. When done wrong, keyboard users can't close them, screen reader users don't know they're open, and everyone gets frustrated.

What Makes a Modal Accessible?

An accessible modal must:

  1. Announce itself to screen readers when it opens
  2. Trap focus inside while open
  3. Return focus to the trigger element when closed
  4. Be closeable with the Escape key
  5. Hide background content from assistive technology

The HTML Structure

<button id="open-modal-btn">Open Settings</button>

<div
  id="modal"
  role="dialog"
  aria-modal="true"
  aria-labelledby="modal-title"
  hidden
>
  <h2 id="modal-title">Settings</h2>
  <!-- Modal content -->
  <button id="close-modal-btn">Save & Close</button>
</div>

Key ARIA Attributes

  • role="dialog": Tells screen readers this is a dialog
  • aria-modal="true": Indicates background content is inert
  • aria-labelledby: Points to the modal's title

The Native Dialog Element

Modern browsers support the <dialog> element, which handles much of this automatically:

<button id="open-btn">Open Settings</button>

<dialog id="settings-dialog" aria-labelledby="dialog-title">
  <h2 id="dialog-title">Settings</h2>

  <form method="dialog">
    <label for="theme">Theme</label>
    <select id="theme">
      <option>Light</option>
      <option>Dark</option>
    </select>

    <button value="save">Save</button>
  </form>
</dialog>

<script>
const dialog = document.getElementById('settings-dialog');
document.getElementById('open-btn').addEventListener('click', () => {
  dialog.showModal();
});
</script>

The native dialog automatically:

  • Traps focus
  • Closes on Escape
  • Makes background inert
  • Returns focus when closed

Common Modal Mistakes

Not Trapping Focus

If users can Tab out of the modal to content behind it, that's a major problem.

Not Returning Focus

When the modal closes, focus should return to the element that opened it.

No Escape Key Support

Users expect Escape to close modals. Always implement this.

Testing Modals

  1. Can you open the modal with keyboard?
  2. Does focus move into the modal?
  3. Is focus trapped inside?
  4. Does Escape close it?
  5. Does focus return to the trigger?
  6. Is the modal announced by screen readers?