Tailwind CSS cookbook · Intermediate

Create an accessible modal dialog

Show a modal with a dimmed backdrop that traps focus and closes with Escape, using as little JavaScript as possible.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Use the native <dialog> element and showModal(): the browser handles the top layer, focus trapping and Escape. Style the backdrop with the backdrop: variant and the open state with open:.

Solution

Create an accessible modal dialogTry it yourself
<div class="p-6">
  <button onclick="document.getElementById('confirm').showModal()" class="rounded-lg bg-rose-600 px-4 py-2 font-medium text-white hover:bg-rose-500">Delete project</button>
  <dialog id="confirm" class="m-auto max-w-sm rounded-2xl p-6 shadow-2xl backdrop:bg-slate-900/60 backdrop:backdrop-blur-xs">
    <h2 class="text-lg font-semibold">Delete this project?</h2>
    <p class="mt-2 text-sm text-slate-600">This removes all its files. You can't undo this.</p>
    <form method="dialog" class="mt-6 flex justify-end gap-3">
      <button class="rounded-lg px-4 py-2 font-medium ring-1 ring-slate-300 hover:bg-slate-50">Cancel</button>
      <button class="rounded-lg bg-rose-600 px-4 py-2 font-medium text-white hover:bg-rose-500">Delete</button>
    </form>
  </dialog>
</div>

Pitfalls

  • Building modals from divs with fixed inset-0; you then have to implement focus trapping, Escape and aria-modal yourself.
  • Forgetting m-auto: Preflight resets the dialog's default centring margin.

Variations

  • Animate opening with transition plus starting:open:opacity-0 (CSS @starting-style).
  • In React use Headless UI's Dialog or Radix Dialog for the same behaviour with portals.

Further reading: Tailwind CSS docs

Reference: https://tailwindcss.com/docs/hover-focus-and-other-states#backdrop

More Tailwind CSS recipes

Was this page helpful?