Interactive
HTML5
The <dialog> element represents a dialog box or interactive component such as a dismissible alert, inspector, or subwindow. It provides native browser support for modals and popups with built-in accessibility features, keyboard handling, and focus management.
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('myDialog').showModal()">
Open Dialog
</button>
<dialog id="myDialog">
<h2>Welcome!</h2>
<p>This is a native HTML dialog element.</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
</style>
Attribute Value Description openBoolean When present, the dialog is visible (use JavaScript methods instead)
The <dialog> element supports all global attributes .
Understanding the difference between modal and non-modal dialogs is crucial:
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('modal').showModal()">
Open Modal Dialog
</button>
<dialog id="modal">
<h2>Modal Dialog</h2>
<p><strong>This is a modal:</strong></p>
<ul>
<li>Blocks interaction with page content</li>
<li>Shows a backdrop</li>
<li>Traps focus inside dialog</li>
<li>Closes with Escape key</li>
<li>Centered on screen</li>
</ul>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
max-width: 500px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.6);
backdrop-filter: blur(3px);
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #2563eb;
}
</style> Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('nonmodal').show()">
Open Non-Modal Dialog
</button>
<dialog id="nonmodal">
<h2>Non-Modal Dialog</h2>
<p><strong>This is non-modal:</strong></p>
<ul>
<li>Allows interaction with page</li>
<li>No backdrop</li>
<li>No focus trap</li>
<li>Escape key doesn't close</li>
<li>Positioned in normal flow</li>
</ul>
<button onclick="document.getElementById('nonmodal').close()">
Close
</button>
</dialog>
<p style="margin-top: 2em;">
You can still interact with this text and other page elements
when the non-modal dialog is open.
</p>
<style>
dialog {
padding: 2em;
border: 2px solid #3b82f6;
border-radius: 8px;
max-width: 500px;
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
margin-top: 1em;
}
button:hover {
background: #2563eb;
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<button id="showModalBtn">Show Modal</button>
<button id="showBtn">Show Non-Modal</button>
<dialog id="controlledDialog">
<h2>Dialog Control Methods</h2>
<p>This dialog demonstrates JavaScript control.</p>
<button id="closeBtn">Close Dialog</button>
<button id="returnBtn">Close with Return Value</button>
</dialog>
<div id="status" style="margin-top: 1em; padding: 1em;
background: #f3f4f6; border-radius: 4px;">
Status: Dialog is closed
</div>
<script>
const dialog = document.getElementById('controlledDialog');
const status = document.getElementById('status');
document.getElementById('showModalBtn').addEventListener('click', () => {
dialog.showModal();
status.textContent = 'Status: Modal dialog opened';
});
document.getElementById('showBtn').addEventListener('click', () => {
dialog.show();
status.textContent = 'Status: Non-modal dialog opened';
});
document.getElementById('closeBtn').addEventListener('click', () => {
dialog.close();
status.textContent = 'Status: Dialog closed (no return value)';
});
document.getElementById('returnBtn').addEventListener('click', () => {
dialog.close('confirmed');
status.textContent = 'Status: Dialog closed with return value';
});
dialog.addEventListener('close', () => {
const returnValue = dialog.returnValue;
if (returnValue) {
status.textContent += ' - Return value: ' + returnValue;
}
});
</script>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
button {
padding: 0.75em 1em;
margin: 0.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background: #2563eb;
}
</style>
Use method="dialog" to close dialogs with form submission:
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('formDialog').showModal()">
Open Form Dialog
</button>
<dialog id="formDialog">
<h2>User Preferences</h2>
<form method="dialog">
<label>
Name:
<input type="text" name="name" required>
</label>
<br>
<label>
Email:
<input type="email" name="email" required>
</label>
<br>
<label>
Newsletter:
<input type="checkbox" name="newsletter">
Subscribe to newsletter
</label>
<br><br>
<button value="cancel" formnovalidate>Cancel</button>
<button value="save" type="submit">Save</button>
</form>
</dialog>
<div id="result" style="margin-top: 1em; padding: 1em;
background: #f0fdf4; border-radius: 4px; display: none;">
</div>
<script>
const formDialog = document.getElementById('formDialog');
const result = document.getElementById('result');
formDialog.addEventListener('close', () => {
const returnValue = formDialog.returnValue;
result.style.display = 'block';
if (returnValue === 'save') {
result.style.background = '#f0fdf4';
result.textContent = '✓ Form saved with value: ' + returnValue;
} else {
result.style.background = '#fef2f2';
result.textContent = '✗ Form cancelled with value: ' + returnValue;
}
});
</script>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
max-width: 400px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
label {
display: block;
margin: 1em 0;
}
input[type="text"],
input[type="email"] {
display: block;
width: 100%;
padding: 0.5em;
margin-top: 0.25em;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
padding: 0.75em 1.5em;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 0.5em;
}
button[value="cancel"] {
background: #e5e7eb;
color: #374151;
}
button[value="save"] {
background: #3b82f6;
color: white;
}
button:hover {
opacity: 0.9;
}
</style>
The ::backdrop pseudo-element styles the background overlay:
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('basicBackdrop').showModal()">
Basic Backdrop
</button>
<dialog id="basicBackdrop">
<h2>Simple Backdrop</h2>
<p>Semi-transparent black overlay.</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
<style>
#basicBackdrop::backdrop {
background: rgba(0, 0, 0, 0.7);
}
dialog {
padding: 2em;
border: none;
border-radius: 8px;
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style> Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('blurBackdrop').showModal()">
Blur Backdrop
</button>
<dialog id="blurBackdrop">
<h2>Blurred Background</h2>
<p>Creates a frosted glass effect.</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
<style>
#blurBackdrop::backdrop {
background: rgba(255, 255, 255, 0.3);
backdrop-filter: blur(10px);
}
dialog {
padding: 2em;
border: none;
border-radius: 8px;
box-shadow: 0 8px 16px rgba(0, 0, 0, 0.2);
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style> Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('gradientBackdrop').showModal()">
Gradient Backdrop
</button>
<dialog id="gradientBackdrop">
<h2>Gradient Background</h2>
<p>Colorful gradient overlay.</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
<style>
#gradientBackdrop::backdrop {
background: linear-gradient(
135deg,
rgba(59, 130, 246, 0.5) 0%,
rgba(139, 92, 246, 0.5) 100%
);
}
dialog {
padding: 2em;
border: none;
border-radius: 8px;
background: white;
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<button onclick="confirmDelete()">Delete Item</button>
<dialog id="confirmDialog">
<h2>⚠️ Confirm Deletion</h2>
<p>Are you sure you want to delete this item? This action cannot
be undone.</p>
<form method="dialog">
<button value="cancel">Cancel</button>
<button value="delete" class="danger">Delete</button>
</form>
</dialog>
<div id="message" style="margin-top: 1em; padding: 1em;
border-radius: 4px; display: none;"></div>
<script>
const confirmDialog = document.getElementById('confirmDialog');
const message = document.getElementById('message');
function confirmDelete() {
confirmDialog.showModal();
}
confirmDialog.addEventListener('close', () => {
message.style.display = 'block';
if (confirmDialog.returnValue === 'delete') {
message.style.background = '#fee2e2';
message.style.color = '#991b1b';
message.textContent = '✓ Item deleted successfully';
} else {
message.style.background = '#f3f4f6';
message.style.color = '#374151';
message.textContent = 'Deletion cancelled';
}
});
</script>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
max-width: 400px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.6);
}
dialog h2 {
margin-top: 0;
color: #dc2626;
}
button {
padding: 0.75em 1.5em;
border: none;
border-radius: 4px;
cursor: pointer;
margin-right: 0.5em;
font-weight: 600;
}
button[value="cancel"] {
background: #e5e7eb;
color: #374151;
}
button.danger {
background: #dc2626;
color: white;
}
button:hover {
opacity: 0.9;
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<div style="display: grid; grid-template-columns: repeat(3, 1fr);
gap: 0.5em; max-width: 400px;">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Crect width='120' height='120' fill='%233b82f6'/%3E%3Ctext x='50%25' y='50%25' text-anchor='middle' dy='.3em' fill='white' font-size='24'%3E1%3C/text%3E%3C/svg%3E"
onclick="openLightbox(this.src)" alt="Image 1"
style="cursor: pointer; width: 100%;">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Crect width='120' height='120' fill='%2310b981'/%3E%3Ctext x='50%25' y='50%25' text-anchor='middle' dy='.3em' fill='white' font-size='24'%3E2%3C/text%3E%3C/svg%3E"
onclick="openLightbox(this.src)" alt="Image 2"
style="cursor: pointer; width: 100%;">
<img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Crect width='120' height='120' fill='%23f59e0b'/%3E%3Ctext x='50%25' y='50%25' text-anchor='middle' dy='.3em' fill='white' font-size='24'%3E3%3C/text%3E%3C/svg%3E"
onclick="openLightbox(this.src)" alt="Image 3"
style="cursor: pointer; width: 100%;">
</div>
<dialog id="lightbox">
<img id="lightboxImage" src="" alt="" style="max-width: 100%;
max-height: 80vh; display: block;">
<form method="dialog">
<button style="position: absolute; top: 1em; right: 1em;">
✕ Close
</button>
</form>
</dialog>
<script>
const lightbox = document.getElementById('lightbox');
const lightboxImage = document.getElementById('lightboxImage');
function openLightbox(src) {
lightboxImage.src = src;
lightbox.showModal();
}
</script>
<style>
#lightbox {
padding: 0;
border: none;
background: transparent;
max-width: 90vw;
max-height: 90vh;
}
#lightbox::backdrop {
background: rgba(0, 0, 0, 0.9);
}
#lightbox button {
background: rgba(0, 0, 0, 0.7);
color: white;
border: none;
padding: 0.75em 1em;
cursor: pointer;
border-radius: 4px;
}
#lightbox button:hover {
background: rgba(0, 0, 0, 0.9);
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<button onclick="showAlert('success', 'Operation completed!')">
Success
</button>
<button onclick="showAlert('error', 'Something went wrong!')">
Error
</button>
<button onclick="showAlert('info', 'Just so you know...')">
Info
</button>
<dialog id="alertDialog" class="alert-dialog">
<div id="alertContent"></div>
<form method="dialog">
<button>OK</button>
</form>
</dialog>
<script>
const alertDialog = document.getElementById('alertDialog');
const alertContent = document.getElementById('alertContent');
function showAlert(type, message) {
const icons = {
success: '✓',
error: '✕',
info: 'ℹ'
};
const colors = {
success: '#10b981',
error: '#ef4444',
info: '#3b82f6'
};
alertContent.innerHTML =
'<h2 style="color: ' + colors[type] + '; margin-top: 0;">' +
icons[type] + ' ' +
type.charAt(0).toUpperCase() + type.slice(1) +
'</h2><p>' + message + '</p>';
alertDialog.showModal();
}
</script>
<style>
.alert-dialog {
padding: 2em;
border: none;
border-radius: 12px;
min-width: 300px;
text-align: center;
}
.alert-dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
button {
padding: 0.75em 1.5em;
margin: 0.25em;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: 600;
}
.alert-dialog button {
background: #3b82f6;
color: white;
margin-top: 1em;
min-width: 100px;
}
</style>
Modal dialogs automatically trap focus and restore it on close:
Interactive code playground requires JavaScript. Here's the code:
<input type="text" placeholder="Focus returns here after closing"
id="firstInput">
<button onclick="document.getElementById('focusDialog').showModal()">
Open Dialog
</button>
<dialog id="focusDialog">
<h2>Focus Management</h2>
<p>Try pressing Tab to navigate. Focus stays inside the dialog!</p>
<input type="text" placeholder="First input" autofocus>
<input type="text" placeholder="Second input">
<form method="dialog">
<button>Close (focus returns to button)</button>
</form>
</dialog>
<style>
input, button {
display: block;
margin: 0.5em 0;
padding: 0.75em;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
background: #3b82f6;
color: white;
border: none;
cursor: pointer;
}
dialog {
padding: 2em;
border: none;
border-radius: 8px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
dialog input {
width: 100%;
}
</style>
Modal dialogs close when the user presses Escape:
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('escapeDialog').showModal()">
Open (Press Escape to Close)
</button>
<dialog id="escapeDialog">
<h2>Escape Key Support</h2>
<p>Press the Escape key to close this modal dialog.</p>
<p>This is built-in behavior for modal dialogs!</p>
<form method="dialog">
<button>Or click to close</button>
</form>
</dialog>
<div id="escapeLog" style="margin-top: 1em; padding: 1em;
background: #f3f4f6; border-radius: 4px; min-height: 40px;">
<strong>Event log:</strong>
<div id="log"></div>
</div>
<script>
const escapeDialog = document.getElementById('escapeDialog');
const log = document.getElementById('log');
escapeDialog.addEventListener('cancel', (event) => {
const entry = document.createElement('div');
entry.textContent = new Date().toLocaleTimeString() +
' - Escape key pressed';
entry.style.color = '#3b82f6';
log.prepend(entry);
});
escapeDialog.addEventListener('close', () => {
const entry = document.createElement('div');
entry.textContent = new Date().toLocaleTimeString() +
' - Dialog closed';
log.prepend(entry);
});
</script>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('backdropDialog').showModal()">
Open (Click Outside to Close)
</button>
<dialog id="backdropDialog">
<h2>Backdrop Click</h2>
<p>Click on the dark area outside this dialog to close it.</p>
<form method="dialog">
<button>Or click here</button>
</form>
</dialog>
<script>
const backdropDialog = document.getElementById('backdropDialog');
backdropDialog.addEventListener('click', (event) => {
const rect = backdropDialog.getBoundingClientRect();
const isInDialog = (
rect.top <= event.clientY &&
event.clientY <= rect.top + rect.height &&
rect.left <= event.clientX &&
event.clientX <= rect.left + rect.width
);
if (!isInDialog) {
backdropDialog.close();
}
});
</script>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.6);
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
Add smooth animations to dialog appearance:
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('animatedDialog').showModal()">
Open Animated Dialog
</button>
<dialog id="animatedDialog" class="animated">
<h2>Smooth Animation</h2>
<p>This dialog slides in with a fade effect.</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
<style>
.animated {
padding: 2em;
border: none;
border-radius: 12px;
opacity: 0;
transform: translateY(-50px);
transition: opacity 0.3s ease, transform 0.3s ease;
}
.animated[open] {
opacity: 1;
transform: translateY(0);
}
.animated::backdrop {
background: rgba(0, 0, 0, 0);
transition: background 0.3s ease;
}
.animated[open]::backdrop {
background: rgba(0, 0, 0, 0.6);
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
The <dialog> element includes excellent built-in accessibility:
Interactive code playground requires JavaScript. Here's the code:
<button onclick="document.getElementById('accessibleDialog').showModal()">
Open Accessible Dialog
</button>
<dialog id="accessibleDialog"
aria-labelledby="dialogTitle"
aria-describedby="dialogDesc">
<h2 id="dialogTitle">Accessible Dialog</h2>
<p id="dialogDesc">
This dialog is properly labeled for screen readers using
aria-labelledby and aria-describedby attributes.
</p>
<form method="dialog">
<button>Close</button>
</form>
</dialog>
<style>
dialog {
padding: 2em;
border: none;
border-radius: 8px;
max-width: 500px;
}
dialog::backdrop {
background: rgba(0, 0, 0, 0.5);
}
button {
padding: 0.75em 1.5em;
background: #3b82f6;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
Use semantic HTML : Include proper headings and structure
Label dialogs : Use aria-labelledby or aria-label
Describe content : Use aria-describedby for additional context
Manage focus : Let browser handle focus trap in modals
Keyboard support : Ensure all actions are keyboard accessible
Clear close options : Provide obvious ways to close
Test with screen readers : Verify announcements are meaningful
Excellent Modern Support
The <dialog> element is now supported in all modern browsers:
Chrome : 37+ (2014)
Firefox : 98+ (2022)
Safari : 15.4+ (2022)
Edge : 79+ (2020)
Opera : 24+ (2014)
Mobile : Varies by browser version
Polyfill Available : For older browsers, use the dialog-polyfill library.
<details> - Disclosure widgets
<summary> - Details summary
Popover API - Alternative for non-modal overlays
Use showModal() for modals : Don’t use the open attribute
Always provide close mechanism : Button, form, or backdrop click
Use form method=“dialog” : Simplifies form-based dialogs
Style the backdrop : Make it clear the page is blocked
Handle focus properly : Let browser manage for modals
Test keyboard navigation : Tab, Escape, Enter should work
Provide clear labels : Use descriptive headings
Don’t nest dialogs : Avoid opening dialogs from dialogs
Test on mobile : Ensure dialogs work on small screens
Consider animations : Smooth transitions improve UX
Learn More: