Introducing the new dialog element

Hello, Habr! I present to you the translation of the article " Meet the New Dialog Element " by Keith J. Grant.

HTML 5.2 introduced a new dialog element for native modal windows. At first glance, it seems pretty simple (it is), but after playing with it, I found that it has some great features that are easy to miss.

I have embedded a full-fledged demo at the end of the article, but if you want to look at it while reading, you can find it here .

Here is an example of basic markup for a dialog box:


  Native dialog box!

The open attribute means that the dialog is visible. Without this attribute, the dialog will be hidden until you use JavaScript to make it visible. Without any stylization, the dialogue looks like this:



On the page, it is positioned absolutely, so that it appears in front of all the content, as you might expect, and it is horizontally centered. By default, its width is equal to the width of the content inside.

Basic operations


JavaScript has several methods and properties to make working with the dialog element easier . showModal () and close () are the two methods you may need most.

const modal = document.querySelector('dialog');
// показывает диалог (добавляет атрибут "open")
modal.showModal();
// скрывает диалог (удаляет атрибут "open")
modal.close();

When you use showModal () to open a dialog, a background is added to the page that blocks user interaction with content outside the modal window. By default, the background is completely transparent, but you can make it visible with CSS (more on this below).

Pressing Esc closes the dialog, and you can also create a close button with a call to the close () method .

There is a third method, show () , which also shows a modal window, but without an accompanying background. The user will be able to interact with elements outside the dialog.

Browser support and polyfill


At this point dialog is only supported in Chrome. Firefox provides basic styling, however, to use the JavaScript API, the user must explicitly enable this feature. I think Firefox will soon turn it on by default.

Fortunately, we have a polyfill that supports both JavaScript behavior and default styling. To use it, set dialog-polyfill to npm, or use the good old script tag . Polyfill works in IE9 and higher.

When using polyfill, each dialogue on the page must be initialized:

dialogPolyfill.registerDialog(modal);

This trick will not replace the native behavior of the dialog for browsers that support it.

Stylization


Opening and closing a modal window is nice, but it doesn’t look very professional. Adding styling is as easy as styling any other element. The background can be styled using the new pseudo-element :: backdrop .

dialog {
  padding: 0;
  border: 0;
  border-radius: 0.6rem;
  box-shadow: 0 0 1em black;
}
dialog::backdrop {
  /* сделает фон черным полупрозрачным */
  background-color: rgba(0, 0, 0, 0.4);
}

For older browsers that use polyfill, this pseudo-element will not work. In this case, the polyfill adds the .backdrop element , which immediately follows the dialog. You can style it with CSS something like this:

dialog + .backdrop {
  background-color: rgba(0, 0, 0, 0.4);
}

Add a little more markup for styling. Common approach: break the dialog box into the header, body and footer:


By adding some CSS, you can make the modal window look exactly as you need it:



More control


Often we want a little feedback from the user through the dialog box. When the dialog closes, you can pass the string value to the close () method . This value is assigned to the returnValue property of the DOM dialog element , so you can read it later:

modal.close('Accepted');
console.log(modal.returnValue); // выведет `Accepted`

There are also other events that you can subscribe to. Two very useful ones: close (triggers when the window closes ) and cancel (triggers when you press Esc to close the window).

The only missing thing is the ability to close the modal window when you click on the background, but there is a workaround. A click on the background triggers a click event on the dialog as on the target element. And if you create a dialog so that the children will fill the entire space of the dialog box, these children will be targeted for any clicks inside the dialog. Thus, you can subscribe to events of a click on the dialog, and close it when the immediate goal of the click is the dialog window itself:

modal.addEventListener('click', (event) => {
  if (event.target === modal) {
    modal.close('cancelled');
  }
});

It is not perfect, but it works. Please let me know if you find a better way to track background clicks.

Working demo


I worked a lot on the demo below. Play around with it and see what else you can do with the dialog element . The demo includes polyfill, so it will work in most browsers.

Link to the demo .

Also popular now: