Skip to content
Motion & micro-interactionsLesson 7 of 8Beginner8 min

Toast / notification motion

A toast should arrive with a spring and leave with a quiet ease — and announce itself to screen readers without stealing focus.

Kept on this device only.

In one line: a toast that springs up when it arrives and eases quietly out of the way when it leaves reads as a confident, momentary aside — provided it announces itself to assistive tech and never grabs your focus.

What it is

A toast is a small, transient message that appears at the edge of the screen to confirm something happened — "Changes saved", "Couldn't connect", "A new version is available". It is not a dialog: it doesn't block the page, it doesn't demand a decision, and it goes away on its own after a few seconds.

The motion has two distinct halves. On the way in, the toast slides up a little and fades on, with a spring — a tiny overshoot that makes it feel like it landed rather than appeared. On the way out, it fades and slides down on a plain ease, quieter and quicker, because a departure shouldn't draw the eye the way an arrival does. In between, it sits still and waits to be read.

Why it matters

The shape of the motion is a message in itself. A spring on entry says something arrived, look here; a soft ease on exit says nothing to see, carry on. Match the two and the toast feels like a considered aside instead of a flicker.

But a toast is also one of the easiest components to make inaccessible. The whole point is to inform, yet the information lives in a region that often appears and vanishes silently — a sighted user catches it, a screen-reader user never hears it. The fix is an aria-live region: additions to it are announced without moving focus, so the message reaches everyone and nobody is yanked out of what they were doing. Get the politeness level right (gentle for routine confirmations, interrupting only for errors), give people a real way to dismiss it and enough time to read it, and the toast earns its place instead of just decorating the corner.

See it

Live demo
Tweak it3
3500
Fire a toast and watch it spring in, then ease out. Dismiss it early too.

How it works

Four decisions carry the whole component:

  1. Enter on a spring, exit on an ease. The arrival uses a spring from a single offset state to rest — one fromto, so just two keyframes, which is all a spring supports. The exit uses a short fixed-duration ease; it's quieter and faster than the entrance on purpose.
  2. AnimatePresence for the exit. A toast that's removed from state would normally vanish instantly. Wrapping the list in AnimatePresence keeps the element mounted long enough to play its exit animation before it's gone.
  3. Auto-dismiss that pauses. A timer removes the toast after about 3.5 seconds. Hovering or focusing the toast pauses that timer, so a reader — or someone tabbing to the dismiss button — never has it disappear mid-thought.
  4. aria-live politeness. The toast region is aria-live="polite" so additions are announced after the screen reader finishes its current utterance. Errors switch to "assertive" to interrupt. Either way focus stays put — the announcement comes to the user, not the other way around.

Build it

Vanilla CSS + a sprinkle of JS
/* Positioned region: toasts stack here without shifting page layout. */
.toast-region {
  position: fixed;
  inset-inline: 0;
  bottom: 1rem;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
  padding-inline: 1rem;
  pointer-events: none;
}
 
.toast {
  pointer-events: auto;
  display: flex;
  gap: 0.75rem;
  max-width: 24rem;
  padding: 0.75rem;
  border: 1px solid var(--border, #2a2a2a);
  border-radius: 0.5rem;
  background: var(--surface-raised, #1b1b1b);
  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.25);
}
 
/* ENTER: spring-ish overshoot via a cubic-bezier with a slight bounce. */
.toast.is-entering {
  animation: toast-in 320ms cubic-bezier(0.22, 1.2, 0.36, 1);
}
 
/* EXIT: quieter and quicker — a plain ease down and out. */
.toast.is-leaving {
  animation: toast-out 220ms cubic-bezier(0.4, 0, 1, 1) forwards;
}
 
@keyframes toast-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: translateY(0); }
}
 
@keyframes toast-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(12px); }
}
 
/* Reduced motion: appear/disappear with opacity only, no slide. */
@media (prefers-reduced-motion: reduce) {
  .toast.is-entering,
  .toast.is-leaving {
    animation: none;
  }
}

Make it yours

Use the controls beside the demo above to change variant, dock position, and auto-dismiss — each change updates the example live.

Experiment in the playground

Reproduce it with an LLM

Reproduce it with an LLM

You are a senior front-end engineer. Build a toast notification with tasteful enter/exit motion in React using the Motion library: it slides up and fades in on appear, and slides down and fades out on dismiss, with a spring on entry and a quick ease on exit. Requirements: the toast is an aria-live='polite' region (assertive only for errors) so screen readers announce it; it is dismissible by a real button and auto-dismisses after a few seconds (pausing on hover/focus); animate only transform and opacity; fully disable motion (appear/disappear instantly) under prefers-reduced-motion: reduce; never animate layout. Return only the component code with imports.

Pitfalls & accessibility

Further reading

  • Your animation library's AnimatePresence docs, for how exit animations survive unmounting.
  • The ARIA live-region guidance on politeness levels, for when polite beats assertive.
  • The platform notification and status-message patterns, for how transient feedback reaches assistive tech without stealing focus.