5

The <dialog> element is now cross-browser compatible (since March 2022).

I tried my hand at it today and familiarised myself with:

  • HTML

    • <dialog>
  • JavaScript

    • .show()
    • .showModal()
    • .close()
  • CSS

    • ::backdrop

Everything seems straightforward but the one thing I've been unable to achieve so far is: fading up the backdrop.

For instance, if I want the final color of the backdrop to be:

  • background-color: rgba(0, 0, 63, 0.8);

but have it transition (or animate) to that background-color from:

  • background-color: rgba(0, 0, 0, 0);

is this even possible?


Here is my (non-working) example:

const myButton = document.querySelector('button');
const myDialog = document.querySelector('dialog');

const requestDialog = () => {
  myDialog.showModal();
  setTimeout(() => myDialog.classList.add('fadeUp'), 400);
}

myButton.addEventListener('click', requestDialog, false);
body {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 180px;
}

button {
  position: absolute;
  top: 6px;
  left: 6px;
  cursor: pointer;
}

dialog::backdrop {
  background-color: rgba(0, 0, 0, 0);
  transition: backgroundColor 0.6s ease-out;
}

dialog.fadeUp::backdrop {
  background-color: rgba(0, 0, 63, 0.8);
}
<button type="button">Click me to<br />Request Dialog</button>

<dialog>
  <h2>My Dialog</h2>
</dialog>
Vega
  • 27,856
  • 27
  • 95
  • 103
Rounin
  • 27,134
  • 9
  • 83
  • 108
  • 1
    If you use a box-shadow, it might work and be close enough to what you try to do : `dialog { box-shadow: 0 0 0 100vw rgba(0, 0, 0, 0); transition: 2s ease-out; } dialog.fadeUp { box-shadow: 0 0 0 100vw rgba(0, 0, 63, 0.8); transition: 2s ease-out; }` – G-Cyrillus Apr 04 '22 at 22:03
  • 1
    Caniuse says that dialog has good browser support, but support for the actual `::backdrop` pseudo element varies WIDELY and likely transitions/animations aren't implemented yet – Zach Jensz Apr 05 '22 at 04:26
  • 1
    Thanks @ZachJensz - that's reassuring to read, since I'd rather work on the basis that `::backdrop` pseudo-element transitions and animations aren't working in April 2022 because _"We haven't got on to that yet"_ than _"That's never going to be a thing."_ – Rounin Apr 05 '22 at 08:30
  • [This codepen](https://codepen.io/kevinpowell/pen/PoEmLww) might help – Zach Jensz Apr 05 '22 at 23:11
  • I can't seem to get the codepen to work here, the fade in animation is fading in instantly – Zach Jensz Apr 05 '22 at 23:51

3 Answers3

5

I was having the same problem but this solved to me.

const dialog = document.querySelector('.modal')

function openModal() {
  dialog.showModal(); // default dialog method
}

function closeModal() {
  dialog.classList.add('close'); // run animation here
  
  dialog.addEventListener('animationend', () => {
    dialog.classList.remove('close')
    dialog.close(); // then run the default close method
  }, {once : true}); // add this to prevent bugs when reopening the modal
}
.modal {
  display: none;
}
/* when the dialog is open by its default method it adds a open tag on the element */
.modal[open] {
  display: flex;
}

.modal[open]::backdrop {
  animation: backdrop-fade 2s  ease forwards;
}

.modal.close::backdrop {
  animation: backdrop-fade 3s ease backwards;
  animation-direction: reverse;
}

@keyframes backdrop-fade {
  from {
    background: transparent;
  }
  to{
    background: rgba(0,0,0);
  }
}
<button onclick="openModal()">open modal</button>
<dialog class="modal">
    <button onclick="closeModal()">close modal</button>
</dialog>
Adriano
  • 51
  • 1
  • Nice! However the modal closes immediately if you press the Escape key, bypassing the close animation. Do you know of a workaround? – Aamir Khan May 04 '23 at 08:51
3

If you use a box-shadow, it might work and be close enough to what you try to do :

dialog {
   box-shadow: 0 0 0 100vw rgba(0, 0, 0, 0);
   transition:  2s ease-out;
 }  
dialog.fadeUp {
   box-shadow: 0 0 0 100vw  rgba(0, 0, 63, 0.8);
   transition:  2s ease-out;
 }
Vega
  • 27,856
  • 27
  • 95
  • 103
G-Cyrillus
  • 101,410
  • 14
  • 105
  • 129
2

G-Cyrillus's answer is almost perfect! Just added the use of max to the box-shadow so that the shadow will cover on mobile devices.

box-shadow: 0 0 0 100vmax rgba(0, 0, 0, 0);

https://stackoverflow.com/a/71764440/19130936

YoshiJL
  • 21
  • 3
  • This is a great suggestion, @YoshiJL. I went back to my code with the intention of updating it and then I saw that instead of `0 0 0 100vw rgba(0, 0, 0, 0);` ... I'd already written: `0 0 0 100vmax rgba(0, 0, 0, 0);`. (Great minds think alike!) – Rounin May 17 '22 at 08:37
  • 1
    Oh that's even better! It's even better supported on older versions. – YoshiJL May 19 '22 at 01:31