DEV Community

J茅r么me Pott
J茅r么me Pott

Posted on • Updated on

馃く Create a modal with zero line of CSS 馃く


HTML 5.2 brought us the dialog element! 馃檶

For now, only Chrome implemented it, but other browser vendors will certainly follow if they want to be fully HTML-compliant. (In Firefox, it is already behind a flag.) There's also a polyfill for it.

Let's now examine this relatively new and shiny HTML element. 馃敩


In the codepen below, I created a fully functional modal without writing a single line of CSS. 馃

So, how does all this work?

Well, it is actually quite simple. We just need to use the dialog element and add the open attribute to display it (by default it is hidden). We can toggle that attribute on by using the showModal method provided on the HTMLDialogElement. We call the close method to toggle it off.

const modal = document.querySelector('#modal')
modal.showModal() // opens the modal
modal.close() // closes the modal

Enter fullscreen mode Exit fullscreen mode

You can notice a few neat things that the dialog element does automatically for us:

  • The dialog is centered in the middle of the screen.
  • The background is dimmed and elements behind the modal can't be interacted with.
  • The dialog has already basic styling (quite ugly, but more on this later).
  • The escape key closes the modal.

And by adding method="dialog" to the form tag:

  • The first interactive element (in the DOM order) is focused.
  • Upon form submission, the dialog is close and the value of the element that triggered the submit event is saved on the returnValue property of the HTMLDialogElement.

In our codepen above, both buttons trigger the closing of the modal. When the modal is closed, it emits a close event. In our demo, modal.returnValue will contain either 'yes' or 'no' (or an empty string if the user presses [escape]).

modal.addEventListener('close', () => {
    console.log(modal.returnValue) // In our case: 'yes', 'no' or ''

Enter fullscreen mode Exit fullscreen mode


The dialog element comes with a default user agent stylesheet, but can be fully customized. You can even change the modal backdrop in this way:

#modal::backdrop {
    background-color: rgba(0, 0, 0, 0.4)

Enter fullscreen mode Exit fullscreen mode

An example of customization using Tailwind CSS


In this post, I only cover some aspects of the dialog element. For detailed information about this topic, I recommend the following links:

Top comments (9)

fgiraldi profile image

Very nice post!
I actually don't get it on what the W3C is up to. Years of using propietary MS IE window.showModalDialog, then going into some HTML standars that ended draw back, and now this, a (brand new) implementation for the same purpose.
I remember when browsers stopped the modal functionality because implementations where so bad. What will be the difference now?
I suppose someone figured out how to make this modals modal to their own window parent, so now, there is no problem in having a modal dialog inside your page, if you want to switch to another tab to see another page, now you just can.
I hope this to be a relief for all of us developers, who need some sort of synchronism in our apps, without being forced to rely on 3rd party libraries or no standard behaviours.
Thanks a lot for the post.
These are great news.

mornir profile image
J茅r么me Pott

Thank you for reading my post 馃槉
Yes, I do think that the end goal is to set standards for better accessibility.

About this, Jen Simmons wrote:

It would allow Authors to remove a bunch of (sadly too often crappy and inaccessible) JavaScript from their websites. bugzilla

samthor profile image
Sam Thorogood

Nice post! There's also a polyfill: (shameless self-promotion)

And Firefox has an incomplete implementation behind a flag:

mornir profile image
J茅r么me Pott

Thank you for your comment!馃槂

I've updated my post to mention your polyfill. But I feel like the biggest 鈥渟elling point鈥 for using the dialog element is its ease of use. Personally, if I have to install a npm package and then register DOM elements, I would rather create my own modal with CSS or install a npm package like vue/react-modal if I am using a framework.

samthor profile image
Sam Thorogood

Sure, but dialog is only supported in Chrome, so in my opinion it's unreasonable to ship it without a polyfill.

I appreciate your argument, but I think it implies that you should always just create your own modal and not use the built-in one :)

Thread Thread
mornir profile image
J茅r么me Pott • Edited

Yes, in the current state of adoption, your polyfill is the only way to use the dialog element in production.

And if a developer uses React or Vue, he/she can easily overcome the polyfill's major limitation (stacking context) by using portals. 鉁岋笍

tunaxor profile image
Angel Daniel Munoz Gonzalez • Edited

Cool Post!
While I do like the Idea of having a native Dialog element, It doesn't always turns to be that good, think of the select element for example, it is always a mess to style one in a good way across browsers, that you end up using a third party library that renders a consistent select element, even the MDN Docs say so:

The <select> element is considered impossible to style consistently cross-platform. However, some styles are workable.

I think this is one of the reasons the dialog element hasn't been rushed to implement.

That being said, it is nice to know it could be an alternative in the future.

mornir profile image
J茅r么me Pott

Thanks for your comment 馃槂

I think that the issue of styling has been taken into consideration in the design of the dialog element. It is very easy to override the default styles and it even provides a pseudo-element (::backdrop) for customizing the background.

So in the end, it is as easy as styling a div tag, but with the added accessibility benefit.

harsh profile image

Thank you so much for this. i was looking for a non css option to create a modal and this is exactly what i needed