vaweGitHub

SpringsSwiftUI

SwiftUI spring()

A damping fraction of 0.825 is the documented default of spring(response:dampingFraction:blendDuration:). Stiffness 157.91, damping 20.73 and mass 1 give a damping ratio of 0.825, so the spring is underdamped. It settles to within 0.1% in 0.69 s. It passes the end value by up to 1% at 0.442 s and crosses it 1 time.

Demo

Progress against time. The time axis runs 0 to 0.69 s, the settle time.0100.51progress50%90%
Dashed: a straight line. The dot and the line move with the box on the right.
SwiftUI spring()
linear

Both boxes take 0.69 s. Playing at 0.5× speed.

Your system asks for reduced motion, so nothing plays. The chart shows the whole move.

Code

A spring has no fixed duration, so the CSS takes the settle time (690 ms) and a linear() string that follows the spring.

css linear()
transition: translate 690ms linear(0, 0.0055, 0.0208, 0.0442, 0.074, 0.1088, 0.1475, 0.1891, 0.2325, 0.2771, 0.3222, 0.3672, 0.4116, 0.455, 0.4972, 0.5379, 0.5769, 0.6141, 0.6493, 0.6825, 0.7137, 0.7429, 0.77, 0.7952, 0.8185, 0.8399, 0.8595, 0.8774, 0.8937, 0.9085, 0.9218, 0.9338, 0.9445, 0.9541, 0.9626, 0.9701, 0.9767, 0.9825, 0.9875, 0.9919, 0.9956, 0.9987, 1.0014, 1.0036, 1.0054, 1.0068, 1.0079, 1.0088, 1.0094, 1.0099, 1.0101, 1.0102, 1.0102, 1.0101, 1.0098, 1.0096, 1.0092, 1.0088, 1.0084, 1.008, 1.0075, 1.0071, 1.0066, 1.0061, 1.0057, 1.0053, 1.0048, 1.0044, 1.004, 1.0037, 1.0033, 1.003, 1.0027, 1.0024, 1.0022, 1.0019, 1.0017, 1.0015, 1.0013, 1.0011, 1);
web animations api
el.animate({ translate: ['0 0', '240px 0'] }, { duration: 690, easing: 'linear(0, 0.0055, 0.0208, 0.0442, 0.074, 0.1088, 0.1475, 0.1891, 0.2325, 0.2771, 0.3222, 0.3672, 0.4116, 0.455, 0.4972, 0.5379, 0.5769, 0.6141, 0.6493, 0.6825, 0.7137, 0.7429, 0.77, 0.7952, 0.8185, 0.8399, 0.8595, 0.8774, 0.8937, 0.9085, 0.9218, 0.9338, 0.9445, 0.9541, 0.9626, 0.9701, 0.9767, 0.9825, 0.9875, 0.9919, 0.9956, 0.9987, 1.0014, 1.0036, 1.0054, 1.0068, 1.0079, 1.0088, 1.0094, 1.0099, 1.0101, 1.0102, 1.0102, 1.0101, 1.0098, 1.0096, 1.0092, 1.0088, 1.0084, 1.008, 1.0075, 1.0071, 1.0066, 1.0061, 1.0057, 1.0053, 1.0048, 1.0044, 1.004, 1.0037, 1.0033, 1.003, 1.0027, 1.0024, 1.0022, 1.0019, 1.0017, 1.0015, 1.0013, 1.0011, 1)', fill: 'both' });
vawe
import { spring, springDuration, springLinear } from '../../core/motion/springs.js';

const k = 157.91, d = 20.73;

// per-frame code (window.seek, vawe.onFrame): t is seconds since the move starts
const x = 240 * spring(t, k, d);

// CSS and Web Animations: 690 ms, the linear() string above
el.animate(
  { translate: ['0 0', '240px 0'] },
  { duration: springDuration(k, d) * 1000, easing: springLinear(k, d), fill: 'both' },
);

Numbers

Stiffness
157.91k, with mass 1
Damping
20.73d, with mass 1
Damping ratio
0.825underdamped
Settle time
0.69 swithin 0.1% of the end
Overshoot
1%peak at 0.442 s
Crosses the end
1time
50% of travel
0.122 s18% of the settle time
90% of travel
0.246 s36% of the settle time
Natural frequency
12.57 rad/ssqrt(k)
Ring period
0.884 sone swing of the overshoot
Peak speed
3.6xtimes the average speed
linear() points
81within 0.13% of travel

Computed with spring() and springDuration() from core/motion/springs.js. The settle time is the last moment the spring is more than 0.1% away from the end value; a library stops its own spring by its own rest thresholds, so its clock can run shorter.

Source of the numbers

SwiftUISwiftUI documentation read on 2026-11-03
spring(response: 0.5, dampingFraction: 0.825): the documented defaultsAnimation.spring(response:dampingFraction:blendDuration:)

Conversion: stiffness = (2 pi / response)^2, damping = 4 pi x dampingFraction / response, with mass 1. The duration-and-bounce forms map to response = duration and dampingFraction = 1 - bounce, the same bounce mapping Motion documents "as SwiftUI does". Apple states bounce 0 is critically damped and bounce 1 is undamped.

The four closest curves in this set, by the average gap between the two springs over their first seconds. A gap of 0.01 is invisible; 0.1 is a different feel.

More springs