← Back to gallery
CSS

Elastic Text Custom Easing Tradeoffs

A transform-only text snap showcase that uses bounded CSS cubic-bezier overshoot while documenting the boundary where true spring physics should move to JavaScript.

Duration
2s
Resolution
1440×900
Format
CSS
elasticspring-easecustom-easingtransformprefers-reduced-motion

Text Snap / Cubic-bezier Boundary

Elastic Text Custom Easing

Word-level transforms use a bounded overshoot curve to create elastic text snap without turning the pattern into a JavaScript spring simulation.

product badge elastic snap - 1.1s cycle · 1.00 intensity

NewMotion

Short label · tight rebound

Product Badge

A compact badge snaps into place with one visible overshoot and no layout-affecting width change.

The curve overshoots once, settles quickly, and avoids repeated bounce cycles that should be delegated to a spring.

  • cubic-bezier
  • overshoot
  • transform

ElasticInterface

Word stagger · readable dwell

Headline Snap

Each word resolves in sequence, giving a headline a tactile entrance while the baseline remains stable.

Transform and opacity animate only the inline spans; surrounding layout never recalculates during the snap.

  • word stagger
  • baseline stable
  • layout safe

SavedCleanly

Subtle UI feedback

Toast Confirmation

A small confirmation label uses a reduced overshoot so it reads as feedback rather than a playful bounce.

Amplitude stays low and the end frame is stable, so a repeated toast stack will not feel jumpy.

  • feedback
  • single rebound
  • reduce-safe

Elastic inspector

Product Badge

NewMotion

Motion contract
The curve overshoots once, settles quickly, and avoids repeated bounce cycles that should be delegated to a spring.
Accessibility
Reduced motion removes the overshoot and uses a short opacity transition so the copy still appears immediately.

Keep the rebound short for labels that may appear near interactive controls. The transform is isolated to the text run.

css
.elastic-word {
  display: inline-block;
  transform-origin: 50% 100%;
  animation: elasticSnap 1.10s cubic-bezier(0.22, 1.45, 0.36, 1) both;
}

@keyframes elasticSnap {
  0% { opacity: 0; transform: translateY(calc(18px * 1.00)) scale(0.92); }
  72% { transform: translateY(calc(-4px * 1.00)) scale(1.04); }
  100% { opacity: 1; transform: translateY(0) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .elastic-word { animation: none; }
}