Easing for an exit: curve, duration and what to avoid
Use launch for an exit, over 0.35 to 0.6 of the entrance (0.3 s after a 0.5 s one); 0.18 to 0.3 s when the entrance length is unknown. launch reaches 50% of its travel at 77% of the time and 90% at 96%. Avoid an exit on the entrance’s own ease: it arrives while leaving.
Demo
launch
linear
The same move with launch and with linear. If your system asks for reduced motion, nothing plays and the final state shows.
Ease and duration
- Duration
- 0.35 to 0.6 of the entrance (0.3 s after a 0.5 s one); 0.18 to 0.3 s when the entrance length is unknown
- Halfway at
- 77% of the time90% of the travel at 96%
What to avoid
An exit on the entrance’s own ease: it arrives while leaving. Use leave only for a settle or a hand-off the page names.
Code
@keyframes leave {
from { opacity: 1; translate: 0 0; }
to { opacity: 0; translate: 0 -1.2vh; }
}
.target {
animation: leave 300ms cubic-bezier(0.3333, 0, 0.75, 0.25) forwards;
}el.animate(
[{ opacity: '1', translate: '0 0' }, { opacity: '0', translate: '0 -1.2vh' }],
{ duration: 300, easing: 'cubic-bezier(0.3333, 0, 0.75, 0.25)', fill: 'forwards' },
);animation-timing-function: linear(0, 0.0005, 0.0019, 0.0042, 0.0074, 0.0116, 0.0166, 0.0226, 0.0296, 0.0375, 0.0463, 0.0561, 0.0669, 0.0787, 0.0916, 0.1055, 0.1205, 0.1367, 0.154, 0.1725, 0.1922, 0.2133, 0.2357, 0.2595, 0.2848, 0.3117, 0.3402, 0.3704, 0.4025, 0.4365, 0.4727, 0.5111, 0.5519, 0.5953, 0.6416, 0.6911, 0.7441, 0.8009, 0.862, 0.9282, 1);import { EASE } from '../../core/motion/presets.js';
el.animate(keyframes, { duration: 300, easing: EASE.launch, fill: 'both' });Measured source
Measured on ChatGPT and Vercel Analytics clips at 30 fps, read off frames, plus or minus 33 ms. The numbers live in UI, imported from core/motion/presets.js.
| Preset | Value | Measured |
|---|---|---|
| Exit | fade 300 ms, drift -1.2vh | The whole window fades in 0.3 to 0.4 s to the empty ground. Frame 0 is the same ground. |