Choosing Easing for Enter and Exit Motion

Part of Timing Functions & Easing Curves in Core CSS Animation Fundamentals.

The problem

A design system uses one easing, ease-in-out, and one duration, 300ms, for everything. Menus open sluggishly because they start slowly. Dialogs close with a lingering tail, so the page behind feels blocked for longer than necessary. Toasts drift in and drift out with the same weight, which makes dismissing one feel like it did not register. None of the individual animations is wrong, but the interface feels slower than its durations suggest.

Perceived speed depends on where in the animation the motion happens, not only on its total length.

Root cause analysis: attention is at the start of an entrance and the end of an exit

Entrances should decelerate. When something appears, the user wants to see it and read it. An ease-out curve covers most of the distance in the first part of the duration and slows into the final position, so content is nearly in place almost immediately and the settling motion is what remains. It reads as responsive. An ease-in entrance does the opposite — nothing seems to happen, then the element rushes in at the end — which reads as lag.

Exits should accelerate. When something leaves, the user has finished with it and their attention has moved on. An ease-in curve starts gently and speeds away, so the element seems to get out of the way decisively. An ease-out exit leaves the element crawling slowly off screen at the end, occupying attention it no longer deserves.

Moves within the view use both. An element that starts and ends visible — a card reordering, a panel resizing, a shared element morphing — is watched throughout, so it should accelerate out of its start and decelerate into its end: ease-in-out.

Exits should be shorter. Because nobody watches an exit closely, it can be quicker than the entrance. A common ratio is about two-thirds: a 240ms entrance with a 160ms exit. The asymmetry makes the interface feel faster without making entrances abrupt.

The three standard curvesEnter decelerates, exit accelerates, move does both.The three standard curves1.000.750.500.250.000.000.250.500.751.00elapsed time (fraction of duration)progressenter: cubic-bezier(0.2, 0.8, 0.2, 1)exit: cubic-bezier(0.4, 0, 1, 1)
Enter decelerates, exit accelerates, move does both.

Step-by-step resolution

Assigning curves across a component libraryThree curves and two duration ratios cover most interface motion.Assigning curves across a component library1Define enter, exit and move easing tokens.One vocabulary for every component2Define entrance durations per size: small, medium, large.Bigger elements travel further and take longer3Derive exit durations as about two-thirds of the entrance.Exits get out of the way4Audit each component: is this motion entering, exiting or moving?Correct curve per transition5Because the entered state owns the transition, put the exit curve on the closed state.Each direction gets its own curve6Keep the asymmetry in reduced-motion fades.
Three curves and two duration ratios cover most interface motion.

Production code pattern

:root {
  --ease-enter: cubic-bezier(0.2, 0.8, 0.2, 1);   /* decelerate */
  --ease-exit:  cubic-bezier(0.4, 0, 1, 1);       /* accelerate */
  --ease-move:  cubic-bezier(0.4, 0, 0.2, 1);     /* both */
  --dur-enter-md: 240ms;
  --dur-exit-md:  160ms;                           /* ~2/3 of enter */
  --dur-move-md:  280ms;
}

.popover {
  /* Closed state: this transition runs when CLOSING, so it uses the exit curve. */
  opacity: 0;
  translate: 0 6px;
  transition:
    opacity var(--dur-exit-md) var(--ease-exit),
    translate var(--dur-exit-md) var(--ease-exit),
    visibility var(--dur-exit-md);
  visibility: hidden;
}
.popover[data-open] {
  /* Open state: this transition runs when OPENING, so it uses the enter curve. */
  opacity: 1;
  translate: 0 0;
  visibility: visible;
  transition:
    opacity var(--dur-enter-md) var(--ease-enter),
    translate var(--dur-enter-md) var(--ease-enter),
    visibility var(--dur-enter-md);
}

/* A card that moves within the list uses the move curve both ways. */
.card { transition: translate var(--dur-move-md) var(--ease-move); }

@media (prefers-reduced-motion: reduce) {
  .popover { translate: none; transition: opacity 90ms var(--ease-exit), visibility 90ms; }
  .popover[data-open] { transition: opacity 140ms var(--ease-enter), visibility 140ms; }
  .card { transition: none; }
}

Rendering Impact: composite. Easing and duration change when intermediate values occur, not what is animated; the popover and card animate opacity and translate only.

The comments on the popover rules are there because the direction is counter-intuitive: the transition declared on the closed state is the one that runs when the popover closes, since the state being entered owns the timing. Putting the exit curve on the open state is the most common mistake when applying this pattern.

How responsive a 240 ms menu entrance tends to feel, by curveIllustrative ratings showing the typical ordering; run your own comparison with real users.How responsive a 240 ms menu entrance tends to feel, by curveease-in entrance3.1 / 7linear entrance4.2 / 7ease-in-out entrance4.6 / 7ease-out entrance5.9 / 7
Illustrative ratings showing the typical ordering; run your own comparison with real users.

Springs, overshoot and emphasis

Deceleration curves can overshoot for playful entrances — a control point above 1 makes the element pass its final position and settle back, like cubic-bezier(0.34, 1.4, 0.64, 1). Use overshoot sparingly: for small elements that benefit from feeling physical, such as badges, toggles and floating buttons, and never for large surfaces, where the bounce moves a big area of the screen. Exits should not overshoot at all; bouncing away from the viewer reads as indecision. The physics behind spring-like curves is covered in approximating spring physics with CSS easing.

Verification checklist

Constraints and trade-offs

  • A single shared curve is simpler to maintain but makes the interface feel slower.
  • Very short exits can look like disappearance rather than motion; keep at least around 100ms.
  • Overshooting entrances can clip inside containers with overflow: clip.
  • Interrupting an entrance with an exit uses the exit curve from the current position, which can feel abrupt.
  • Brand guidelines may define signature curves; map them onto enter, exit and move roles rather than using one everywhere.

Frequently asked questions

Should entrances use ease-in or ease-out?

Ease-out. It moves the element most of the way quickly and settles gently, so content is visible almost immediately.

Why should exits be faster than entrances?

Users are not watching an element leave as closely as one arriving. A shorter exit gets it out of the way and makes the interface feel quicker.

What easing should an element moving on screen use?

Ease-in-out, because it is visible at both ends: it should accelerate from rest and decelerate into its new position.

Where do I put the exit easing in CSS?

On the state being entered when closing, which is usually the closed or default rule. The transition values of the new state control the transition.