Modern, accessible dialogs with the native <dialog> element
Learn how to use HTML's built-in dialog element with hyperscript for cleaner,
more accessible modals with automatic focus management and keyboard handling.
dialognativeaccessibilitymodern HTML
Why Use Native <dialog>?
✅ Automatic Accessibility: Built-in ARIA roles and keyboard handling
✅ Focus Management: Automatic focus trapping and return
✅ ESC Key Handling: Closes on ESC by default (can be prevented)
<!-- Hyperscript call command works with native methods -->
<button _="on click call #my-dialog.showModal()">
Open Dialog
</button>
<dialog id="my-dialog">
<h2>Dialog Title</h2>
<p>Content here</p>
<button _="on click call #my-dialog.close()">Close</button>
</dialog>
Option 3: JavaScript onclick (Also Works):
<!-- Traditional JavaScript approach -->
<button onclick="document.getElementById('my-dialog').showModal()">
Open Dialog
</button>
<dialog id="my-dialog">
<h2>Dialog Title</h2>
<p>Content here</p>
<button onclick="document.getElementById('my-dialog').close()">Close</button>
</dialog>
Form Dialog with Return Value:
<dialog id="form-dialog">
<form method="dialog">
<input type="text"name="username" />
<button type="submit"value="confirmed">Submit</button>
</form>
</dialog>
<!-- Hyperscript is great for handling events and logic! -->
<div _="on close from #form-dialog
get #form-dialog
set result to it.returnValue
if result is 'confirmed'
log 'Form submitted!'
end"></div>
Close on Backdrop Click:
<!-- Check if click was on dialog itself (backdrop) -->
<dialog onclick="if (event.target === this) this.close()">
<!-- Content with stopPropagation to prevent closing -->
<div onclick="event.stopPropagation()">
Dialog content
</div>
</dialog>
Non-Modal Dialog:
<!-- Use show() instead of showModal() -->
<button onclick="document.getElementById('my-dialog').show()">
Open Non-Modal
</button>
<!-- Non-modal allows page interaction -->
<dialog id="my-dialog">
Content here
</dialog>
Key Differences from Custom Modals:
Native methods vs CSS classes: Use dialog.showModal()/dialog.close() instead of adding/removing classes
Form integration:method="dialog" automatically closes dialog on submit
Close event: Listen for close event with hyperscript or JavaScript
Backdrop styling: Use ::backdrop CSS pseudo-element
ESC handling: Built-in, no need for keydown listeners
Accessibility: Native ARIA roles and keyboard navigation included
Browser Support:
The <dialog> element is supported in all modern browsers
(Chrome 37+, Firefox 98+, Safari 15.4+, Edge 79+). Use a polyfill for older browsers if needed.