Skip to main content Accessibility Feedback

An intro to the dialog element

Two years ago, I wrote about how the alert(), prompt(), and confirm() methods were being deprecated. At the time, I lamented that there wasn’t a great replacement for any of them.

That’s no longer the case. Today, I wanted to give you a primer on the dialog element.

Let’s dig in!

The dialog element

The dialog element is a native HTML element that you can use to create custom pop-up modals.

Inside your dialog element, add a form with a method property that has a value of dialog. Whenever the form is submitted, the dialog element will automatically close.

<dialog>
	<p>Hey, don't do that!</p>
	<form method="dialog">
		<button>Ok, sorry!</button>
	</form>
</dialog>

Showing a dialog element

To show a dialog modal, get the element, then run the HTMLDialogElement.showModal() method.

// Get the modal
let modal = document.querySelector('dialog');

// Show the modal
modal.showModal();

You’ll most likely want to do that in response to a user action, like clicking some sort of button.

<button data-show-modal>Show Modal</button>
// Get the button and modal
let btn = document.querySelector('[data-show-modal]');
let modal = document.querySelector('dialog');

// Show the modal
btn.addEventListener('click', function () {
	modal.showModal();
});

Here’s a demo.

Notice how when the modal is open, you cannot interact with the page behind it. The modal can also be closed with the Escape key.

There’s optionally an HTMLDialogElement.show() method, but this does not shift focus to the dialog element. You can also add an open attribute, but in additional to not shifting focus, the user can still interact with the background content.

For accessibility reasons, I’d recommend always using the HTMLDialogElement.showModal() method.

Getting data from modal interactions

Let’s say you wanted to get a yes/no response from a user, not just alert them of something (like a confirm() modal).

Here, we’ll add two buttons to our form. The first one will have a value of cancel, and the second will have a value of confirm.

<dialog>
	<p>Are you <em>sure</em> you want to do that?</p>
	<form method="dialog">
		<button value="cancel">Cancel</button>
		<button value="confirm">Confirm</button>
	</form>
</dialog>

We can listen for close events on our modal. When the event runs, the HTMLDialogElement.returnValue property is the value of the clicked or toggled button.

If the value is not confirm, we can ignore it. Otherwise, we’ll take whatever action is required.

modal.addEventListener('close', function (event) {
	if (modal.returnValue !== 'confirm') return;
	console.log('Confirmed!');
	// Do something...
});

Here’s another demo.

Recreating a prompt() modal with the dialog element

First, let’s add a label and input to our dialog element. In this case, let’s ask the user who their favorite wizard is.

<dialog>
	<form method="dialog">
		<label for="wizard">Who is your favorite wizard?</label>
		<input type="text" id="wizard" name="wizard">
		<button value="cancel">Cancel</button>
		<button value="confirm">Submit</button>
	</form>
</dialog>

In order to get the entered value, we need to update the value attribute on the confirm button to match what the user types into the input field.

You can do that in an external JavaScript file if you want, but our purposes, let’s add a simple oninput event that runs whenever the user types.

To start, we’ll add a #confirm ID to the confirm button. We’ll get the parent form of the input (this), then grab the element with an ID of confirm from the this.form.elements list. Finally, we’ll update it’s value to this.value.

<dialog>
	<form method="dialog">
		<label for="wizard">Who is your favorite wizard?</label>
		<input type="text" id="wizard" name="wizard" oninput="this.form.elements.confirm.value=this.value;">
		<button value="cancel">Cancel</button>
		<button id="confirm" value="confirm">Submit</button>
	</form>
</dialog>

Now the #confirm button’s value will be updated in real time as the user types.

Inside our close event listener, we’ll check if the modal.returnValue is cancel. If so, we’ll return early and do nothing. Otherwise, we can use the modal.returnValue to get the value the user provided.

modal.addEventListener('close', function (event) {
	if (modal.returnValue === 'cancel') return;
	console.log(modal.returnValue);
	// Do something...
});

Here’s another demo.

Is this clunkier than the old methods? Absolutely!

Does it provide more control over look, styling, and content? Also yes.

Styling the dialog and backdrop

You can style the modal element itself using CSS. Target the dialog element to style all modals, or add a selector to target specific ones.

/* Add a purple border */
dialog {
	border: 15px solid rebeccapurple;
}

You can also style the background behind the modal using the dialog::backdrop pseudo-selector.

dialog::backdrop {
	background-color: rgba(0, 0, 0, 0.7);
}

Here’s one last demo.