@starting-style and Discrete Transitions
When to Use
To animate elements transitioning from
display: noneto visible — previously impossible in CSS alone. Also enables transitions on<dialog>and[popover]elements entering and exiting the page.
Decision
| If you need... | Use... | Why |
|---|---|---|
| Animate a dialog or drawer opening | @starting-style + transition-behavior: allow-discrete |
Browser reads start values from @starting-style |
display: none → display: block with transition |
Both allow-discrete AND @starting-style |
Two parts required — the discrete display change needs allow-discrete, the start values need @starting-style |
| Animate a popover appearing | Same pattern as dialog | Popovers use top-layer entry same as <dialog> |
| Complex orchestrated multi-step animation | JS animation library | CSS discrete transitions are linear; choreography needs JS |
Pattern
Animating a <dialog> open and close:
dialog {
opacity: 1;
translate: 0 0;
transition:
opacity 0.3s ease,
translate 0.3s ease,
display 0.3s allow-discrete, /* required for display: none transition */
overlay 0.3s allow-discrete; /* required to hold top-layer during exit */
@starting-style {
/* Values the browser reads BEFORE the element becomes visible */
opacity: 0;
translate: 0 -1rem;
}
}
/* Exit — when dialog is not [open], animate toward these values */
dialog:not([open]) {
opacity: 0;
translate: 0 -1rem;
}
Three required pieces for enter/exit animation:
1. @starting-style block — start values for the enter transition
2. transition-behavior: allow-discrete on display — allows display to be part of transition
3. transition-behavior: allow-discrete on overlay — keeps top-layer elements visible during exit transition
Browser support: Chrome 117, Firefox 129, Safari 17.5. Baseline August 2024. Safe to use.
Common Mistakes
- Omitting the
overlaytransition — the dialog disappears abruptly during exit because it leaves the top layer before the transition completes - Forgetting
@starting-style— without it, the browser has no starting values and the enter transition does not play - Putting animation logic in
@starting-styleinstead oftransition—@starting-styledefines start state only; transitions are still declared on the element normally - Using
animationinstead oftransition—@starting-styleonly works with CSS transitions, not@keyframesanimations
See Also
- ← Scroll-Driven Animations | View Transitions →
- Popover API → uses the same pattern for popover entry/exit
- Reference: MDN @starting-style