The Dialog Element with Entry *and* Exit Animations

Una Kravets blogged the other day that animating entry effects are now supported in the latest stable version of all major browsers. The new cool way to do it, that is. We’ve long had trickery like applying a @keyframe animation with a to frame that would behave like an “entry effect”, but it was a bit awkward and didn’t work in all situations. Specifically one like using the new and very useful <dialog> element.

This bit of code says a lot:

dialog[open] {
  transition: 
    translate 0.7s ease-out, 
    display 0.7s ease-out allow-discrete;

  /* Post-Entry (Normal) State */
  translate: 0 0;

  /* Pre-Entry State */
  @starting-style {
    translate: 0 100vh;
  }
}Code language: CSS (css)

There are two big things at work there:

  1. The display property is listed in the transitions, with the keyword allow-discrete. The code for it is hidden in User-Agent stylesheets, but when a <dialog> moves from close (default) to open, the display goes from none to block. Using this keyword means that the display property is changed after the animation timing, so animations can actually happen.
  2. The @starting-style gives us an opportunity to apply styling to the element just as it’s entering it’s current state, meaning the transition will happen between the styles declared inside and outside that block.

Golf clap. Everything is awesome.

What Una didn’t cover, on purpose surely, was exit animations (because they aren’t in “Baseline” yet, meaning not supported across browsers). But they are supported in Chrome-n-friends land, so I thought it was worth looking at. To me, they are just as interesting, cool, and useful as the entry kind.

Both Entry and Exit

The trick isn’t terribly different than the code above, it’s just to have very specific styles for both the open and closed (i.e. :not([open]) states. Like this:

dialog {
  --duration: 0.34s;

  transition: 
    translate var(--duration) ease-in-out, 
    scale     var(--duration) ease-in-out,
    filter    var(--duration) ease-in-out,
    display   var(--duration) ease-in-out allow-discrete;

  &[open] {

    /* Post-Entry (Normal) State */
    translate: 0 0;
    scale: 1;
    filter: blur(0);

    /* Pre-Entry State */
    @starting-style {
      translate: 0 8vh;
      scale: 1.15;
      filter: blur(8px);
    }
  }

  /* Exiting State */
  &:not([open]) {
    translate: 0 -8vh;
    scale: 1.15;
    filter: blur(8px);
  }
}
Code language: CSS (css)

Check it out:

And a video in case you’re in a browser that doesn’t support it yet:

Note that not only does it have entry and exit animations, but those states are different — which is very cool! Emphasizing that, here’s one where I move the dialog along an offset-path so the exit is really a continuation of the path:

Usage with Popovers

This isn’t exclusively for dialogs, you can make it work with whatever. But naturally open-closable things make the most sense. Like native popovers! Nils Riedemann has a nice demo here:

Wanna learn CSS Animations deeply?

Leave a Reply

Your email address will not be published. Required fields are marked *

Did you know?

Frontend Masters Donates to open source projects. $313,806 contributed to date.