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.
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
<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 withfixed inset-0; you then have to implement focus trapping, Escape andaria-modalyourself. - Forgetting
m-auto: Preflight resets the dialog's default centring margin.
Variations
- Animate opening with
transitionplusstarting: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