Accessible modals
This course covers building modal dialogs with the HTML dialog element instead of div overlays. It explains what showModal() provides natively: the top layer, the backdrop, focus trapping, Escape handling, inertness and focus restore. Lessons cover styling ::backdrop with Tailwind, initial focus and autofocus choices, Tab order, backdrop clicks and scroll locking. It also covers ARIA names, sr-only labels and aria-hidden icons, a reusable ui--dialog Stimulus controller with lazy turbo-frame loading, and a checklist for testing the full dialog lifecycle.
What you'll learn
- ✓What showModal() does natively compared with a div overlay
- ✓Styling the ::backdrop pseudo-element with Tailwind's backdrop: variant
- ✓Focus trapping, initial focus, autofocus choices and focus restore
- ✓Escape, Tab order, backdrop clicks and preventing scroll behind the dialog
- ✓Naming dialogs and labeling icon buttons for screen readers with ARIA
- ✓A reusable ui--dialog Stimulus controller with lazy turbo-frame loading
The `<dialog>` element replaces div overlays
Before HTML added <dialog>, every modal on the web was a <div> with position: fixed, a backdrop built from another <div>, and a pile of JavaScript to manage focus, keyboard events and screen reader announcements. That approach works, but it reimplements browser behavior that the <dialog> element…
Read the full lesson free →Curriculum
7 lessonsThe `<dialog>` element replaces div overlays
How the dialog element and showModal() provide top layer, backdrop, focus trap, Escape and inertness natively.
Styling the `::backdrop` pseudo-element
Styling ::backdrop with Tailwind, three backdrop patterns in the app, color tokens and animating the backdrop.
Focus management: trapping, autofocus, restore
How the browser traps focus, picks initial focus, restores it on close, and why scroll locking needs JavaScript.
Keyboard navigation: Escape, Tab, scroll
The cancel event on Escape, Tab order from the DOM, backdrop click detection, iOS scroll locking and shortcuts.
Screen readers: ARIA roles, labels, live regions
The implicit dialog role, naming with aria-label or aria-labelledby, sr-only labels, aria-hidden icons and aria-describedby.
The reusable `ui--dialog` Stimulus controller
A walkthrough of the ui--dialog controller: lazy turbo-frame loading, scroll lock and closing on backdrop click.
Accessible modals: putting it together
The full dialog lifecycle, a checklist for new dialogs, an audit of the div modal and common mistakes.