Skip to content

Dialog Custom Animation

Custom enter and exit animations replace the built-in slide, in CSS alone. The --opened state mirrors the opened property, so it applies the enter animations the moment the dialog opens, and its absence applies the exit pair the moment it starts closing. The backdrop is animated through the dialog part and the card through the wrapper part.

Reduced Motion

Your system is set to reduce motion, so the animations shown on this page will not play for you.

Custom animation

The backdrop and the card each run their own enter and exit animations. Close the dialog to see the exit pair.

Code

The following example assumes that you have imported the component and set up the theme.

Custom Animation
<div class="dialog-custom-animation">
<button type="button" data-dialog-toggle="animated-dialog">Open animated dialog</button>
</div>
<sv-dialog id="animated-dialog" aria-labelledby="animated-dialog-title" close-button>
2 collapsed lines
<h2 id="animated-dialog-title">Custom animation</h2>
<p>The backdrop and the card each run their own enter and exit animations. Close the dialog to see the exit pair.</p>
</sv-dialog>
<style>
80 collapsed lines
.dialog-custom-animation {
display: flex;
justify-content: center;
button {
padding: 0.5em 1.2em;
font: inherit;
cursor: pointer;
background-color: var(--sv-gray-6);
border: 1px solid var(--sv-gray-5);
border-radius: var(--sv-bdr-rad-md);
}
}
#animated-dialog {
--dialog-open-dur: 500ms;
--dialog-close-dur: 300ms;
/* --ease-*() syntax is replaced with linear() at build time you can use your own easing functions. */
--enter-ease: --ease-out-wobble(2.4);
--exit-ease: --ease-in-back(4);
&::part(dialog) {
backdrop-filter: blur(4px);
}
&:state(--opened)::part(dialog) {
animation: dialog-backdrop-enter var(--dialog-open-dur) ease;
}
&:state(--opened)::part(wrapper) {
animation: dialog-card-enter var(--dialog-open-dur) var(--enter-ease);
}
&:not(:state(--opened))::part(dialog) {
animation: dialog-backdrop-exit var(--dialog-close-dur) ease forwards;
}
&:not(:state(--opened))::part(wrapper) {
animation: dialog-card-exit var(--dialog-close-dur) var(--exit-ease) forwards;
}
/* Custom animations must explicitly honor the user's motion preference. */
@media (prefers-reduced-motion: reduce) {
--dialog-open-dur: 0s;
--dialog-close-dur: 0s;
}
h2 {
margin-block-start: 0;
}
}
@keyframes dialog-backdrop-enter {
from {
opacity: 0;
}
}
@keyframes dialog-backdrop-exit {
to {
opacity: 0;
}
}
@keyframes dialog-card-enter {
from {
opacity: 0;
scale: 0.7;
translate: 0 3rem;
}
}
@keyframes dialog-card-exit {
to {
opacity: 0;
scale: 0.85;
translate: 0 2rem;
}
}
</style>