On this page
A spring animation follows a simulated relationship between position, velocity, and a target. Unlike a fixed-duration easing curve, it can preserve momentum when the target changes. That makes springs useful for draggable panels, expanding controls, and indicators that need to respond while they are already moving. Their value is continuity, not an excuse to make every control bounce.
Choose a distance before choosing physics
Start with a concrete movement, such as an indicator traveling between two tabs. Use the px to rem converter to document the intended distance relative to your typography baseline. The tool converts units; it does not simulate a spring. Measuring endpoints first prevents an attractive demo from hiding an impractical travel distance.
For layout-dependent motion, measure the target in the browser rather than assuming every tab has the same width. Keep the coordinate system consistent: a value measured in CSS pixels should drive a transform expressed in CSS pixels. If you document distances in rem, convert from the actual root font size when calculating runtime positions.
Choose a spring only when its behavior serves the interaction. A direct manipulation that changes destination repeatedly benefits from momentum continuity. A short color transition usually does not. The micro-interaction guide can help identify the feedback being communicated before choosing its implementation.
Understand the three controls
A basic spring pulls toward its target with a force proportional to displacement. Stiffness controls how strongly it pulls. Increasing stiffness usually makes the motion respond faster, but can increase oscillation if damping remains unchanged. Think of stiffness as urgency, not as an independent duration setting.
Damping opposes velocity and removes energy. Too little produces repeated overshoot. More damping reduces oscillation; excessive damping can produce a slow approach even with a strong spring. Mass controls how much the same force changes velocity. A larger mass tends to feel heavier, but its effect depends on the other parameters.
For the ideal linear model, critical damping occurs when damping equals twice the square root of stiffness multiplied by mass. That relationship is more useful than memorizing a magic preset. With stiffness 180 and mass 1, critical damping is approximately 26.8. A damping value of 24 is slightly underdamped and may overshoot modestly.
These numbers are meaningful only within a particular implementation and unit convention. Two libraries may normalize parameters differently or offer duration-based controls that generate a spring internally. Use the Motion spring documentation to inspect the options of one maintained implementation rather than assuming all spring APIs are interchangeable.
Implement an interruptible one-dimensional spring
The following educational implementation moves a decorative element horizontally. It uses a fixed simulation step, bounded frame time, and separate position and velocity tolerances. Production libraries offer more complete scheduling and numerical behavior, but the example makes the underlying state explicit.
const element = document.querySelector(".indicator");
const reduced = matchMedia("(prefers-reduced-motion: reduce)");
const stiffness = 180;
const damping = 24;
const mass = 1;
const step = 1 / 120;
let position = 0;
let velocity = 0;
let target = 0;
let previous = 0;
let accumulator = 0;
let frame = null;
function paint() {
element.style.transform = "translateX(" + position + "px)";
}
function tick(now) {
const elapsed = Math.min((now - previous) / 1000, 0.05);
previous = now;
accumulator += elapsed;
while (accumulator >= step) {
const force = -stiffness * (position - target);
const acceleration = (force - damping * velocity) / mass;
velocity += acceleration * step;
position += velocity * step;
accumulator -= step;
}
if (Math.abs(position - target) < 0.1 &&
Math.abs(velocity) < 0.1) {
position = target;
velocity = 0;
frame = null;
accumulator = 0;
paint();
return;
}
paint();
frame = requestAnimationFrame(tick);
}
function moveTo(nextTarget) {
target = nextTarget;
if (reduced.matches) {
if (frame !== null) cancelAnimationFrame(frame);
frame = null;
accumulator = 0;
position = target;
velocity = 0;
paint();
return;
}
if (frame === null) {
previous = performance.now();
frame = requestAnimationFrame(tick);
}
}
reduced.addEventListener("change", () => moveTo(target));
// Call moveTo(measuredOffset) when selection changes.The target changes without resetting velocity. That is the important distinction: an interrupted spring continues from its present state rather than replaying a canned entrance. The requestAnimationFrame reference explains its timestamp and scheduling behavior. Cancel the outstanding frame and remove listeners when the component is destroyed.
Clamping elapsed time deliberately discards some simulation time after a stall. This favors a stable decorative animation over physically accurate catch-up. Do not reuse this simplified integrator for safety-critical simulations or assume it remains stable with arbitrarily large stiffness values.
Tune against interaction scenarios
Begin near critical damping, then reduce damping only if a small overshoot reinforces the interaction. For a navigation indicator, a barely perceptible settle may be enough. For a drawer containing paragraphs, oscillation can make reading uncomfortable. Content stability should win over a lively transition.
Test three distances: a short neighboring move, a middle-distance move, and the longest expected jump. A spring has no single fixed completion time. Greater displacement can take longer to fall below the same stopping tolerances, so review actual settling time rather than only the initial response.
Test rapid reversals as well. Click the first, last, and middle tabs before the indicator settles. If the indicator appears to sling past its target, increase damping or reconsider whether inherited velocity is appropriate for that component. Drag-release gestures and discrete selections need not share identical settings.
Document settling tolerances in the same units as the simulation. A position threshold alone is insufficient: an element can cross its target at high speed. Requiring both low displacement and low velocity avoids stopping mid-flight. Snap to the exact endpoint when finished so tiny residual differences do not accumulate.
Keep semantics independent of settling
Update selected state as soon as the selection changes, not when the spring stops. Animation communicates state; it must not postpone the actual state. Keyboard navigation, labels, and content visibility should remain correct even if the animation is canceled or the page becomes hidden.
For reduced motion, move directly to the target or use a brief nonspatial cue where appropriate. The MDN reduced-motion documentation describes the preference query. Avoid assuming that a critically damped spring is automatically comfortable simply because it does not bounce.
Profile the animated element with real content. Transforms are generally a better starting point than repeatedly changing layout dimensions, but large layers can still cost memory. Our accessible interface guide provides broader checks for keeping interaction understandable without relying on movement. Prefer a well-tested animation library when gestures, multiple dimensions, or shared lifecycle management make a custom loop difficult to maintain.
Before release, resize the container while the indicator is moving. Recalculate its destination from current layout measurements, then let the same spring approach the revised target. Also test browser zoom and changed text labels. These cases expose assumptions about fixed tab widths that a polished physics preset cannot correct. Include a background-tab test to confirm returning to the page does not launch an enormous catch-up movement.
Key takeaways
- Choose endpoints and units before tuning a spring.
- Tune stiffness, damping, and mass as a connected system.
- Preserve velocity only when continuity helps the interaction.
- Stop using both distance and speed thresholds.
- Keep selection state immediate and offer a motion-free alternative.
Reach designers & developers at work
Put your product next to the tools people use every day. One sponsor per placement, no tracking pixels.
Become a sponsor