DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

Spring vs Tween, and 3 More: I Built a Framer Motion Playground With the Code Beside Each Demo

The Framer Motion docs list every prop, but they can't make you feel the difference between a spring and a tween, or what stiffness and damping actually do to a motion. So I built four live demos with the code next to each — drag the sliders, fling the box, and it lands.

▶ Live demo: https://framer-motion-lab.vercel.app/
Source (React 19 + Framer Motion 11): https://github.com/dev48v/framer-motion-lab

The one insight worth the whole lab

A tween has a fixed duration — it always takes the same time, regardless of distance:

<motion.div animate={{ x: 260 }}
  transition={{ type: "tween", duration: 0.6, ease: "easeInOut" }} />
Enter fullscreen mode Exit fullscreen mode

A spring has no duration. It's physics — stiffness, damping, mass — and it settles naturally:

<motion.div animate={{ x: 260 }}
  transition={{ type: "spring", stiffness: 300, damping: 18, mass: 1 }} />
Enter fullscreen mode Exit fullscreen mode

In the lab you drag those three sliders and watch the box go from bouncy (underdamped, damping ratio ζ < 1) to snappy (critically damped) to sluggish (overdamped) — with the live ζ shown. The reason springs win for anything interactive: they handle interruptions gracefully. Grab a spring mid-animation and it flows to the new target; a tween has to restart its clock.

The other three, in one prop each

Gestures — no state, no handlers:

<motion.div whileHover={{ scale: 1.12, rotate: 3 }} whileTap={{ scale: 0.92 }} />
Enter fullscreen mode Exit fullscreen mode

Drag with a rubber-band edge:

const area = useRef(null);
<div ref={area}>
  <motion.div drag dragConstraints={area} dragElastic={0.2} />
</div>
Enter fullscreen mode Exit fullscreen mode

Stagger — one variant definition orchestrates a whole list:

const container = { show: { transition: { staggerChildren: 0.09 } } };
const item = { hidden: { opacity: 0, y: 18 }, show: { opacity: 1, y: 0 } };
<motion.ul variants={container} initial="hidden" animate="show">
  {items.map(t => <motion.li key={t} variants={item} />)}
</motion.ul>
Enter fullscreen mode Exit fullscreen mode

That's the part that surprises people: the parent's staggerChildren sequences the children automatically — you don't compute delays per item.

Every demo is live and the code updates with your settings. If it made Framer Motion click, a star helps others find it: https://github.com/dev48v/framer-motion-lab

Top comments (2)

Collapse
 
aldo_cve profile image
Aldo

This hits close to home. We recently spent a good chunk of time dialing in the modal entry and exit animations for a core feature, trying to make it feel responsive without being jarring. It's a surprisingly iterative process where the documentation only gets you so far; you really do need to see and feel how different durations, easing curves, or spring physics impact the user's perception of speed and fluidity. We often find ourselves in a similar playground scenario, tweaking values until it just feels right, especially for those micro-interactions that communicate state changes or give feedback.

The choice between a spring and a simple tween, for instance, is one of those subtle decisions that can dramatically influence the perceived 'weight' or 'friendliness' of a UI element. A bouncy spring might work well for a small, playful notification badge or a button hover, but apply that same logic to a full-screen overlay and it can quickly feel sluggish or even unprofessional. For larger elements or critical path interactions in a SaaS product, we often lean towards simpler, well-tuned tweens to prioritize perceived performance and avoid any potential jank on lower-end devices, even if a more complex spring looks nicer in isolation. The trade-off is always there, balancing visual richness with a snappy, consistent user experience.

Collapse
 
frank_signorini profile image
Frank

How do you handle performance with complex spring animations in Framer Motion, have you run into any issues? I'd love to swap ideas on optimizing motion.