0
# Spring System
1
2
React Motion's spring system provides physics-based animation configurations that feel more natural than traditional easing curves. Instead of specifying durations, you define spring characteristics like stiffness and damping to control animation behavior.
3
4
## Capabilities
5
6
### spring Function
7
8
Creates a spring configuration object that defines how a value should animate to its target.
9
10
```javascript { .api }
11
/**
12
* Creates spring configuration for animated values
13
* @param val - Target value for the animation
14
* @param config - Optional spring configuration parameters
15
* @returns OpaqueConfig object for internal use by Motion components
16
*/
17
function spring(val/*: number */, config/*?: SpringHelperConfig */)/*: OpaqueConfig */;
18
```
19
20
**Usage Examples:**
21
22
```javascript
23
import { spring } from 'react-motion';
24
25
// Basic spring with default settings
26
const basicSpring = spring(100);
27
28
// Custom spring configuration
29
const customSpring = spring(100, {
30
stiffness: 120,
31
damping: 17,
32
precision: 0.1
33
});
34
35
// Using in Motion component
36
<Motion
37
style={{
38
x: spring(targetX),
39
y: spring(targetY, {stiffness: 200, damping: 20}),
40
opacity: spring(1, {stiffness: 300, damping: 30})
41
}}
42
>
43
{({x, y, opacity}) => (
44
<div style={{
45
transform: `translate(${x}px, ${y}px)`,
46
opacity
47
}}>
48
Animated element
49
</div>
50
)}
51
</Motion>
52
```
53
54
### SpringHelperConfig Interface
55
56
Configuration object for customizing spring behavior.
57
58
```javascript { .api }
59
/**
60
* Configuration options for spring behavior
61
* All properties are optional and have sensible defaults
62
*/
63
/*::
64
type SpringHelperConfig = {
65
stiffness?: number, // Spring stiffness - higher values create snappier animations (default: 170)
66
damping?: number, // Spring damping - higher values reduce oscillation (default: 26)
67
precision?: number, // Animation precision threshold - smaller values run longer (default: 0.01)
68
};
69
*/
70
```
71
72
### OpaqueConfig Interface
73
74
Internal spring configuration object returned by the spring function. Not meant for direct manipulation.
75
76
```javascript { .api }
77
/**
78
* Internal spring configuration object
79
* Used internally by Motion components - do not modify directly
80
*/
81
/*::
82
type OpaqueConfig = {
83
val: number, // Target value for animation
84
stiffness: number, // Spring stiffness parameter
85
damping: number, // Spring damping parameter
86
precision: number, // Precision threshold for stopping animation
87
};
88
*/
89
```
90
91
### presets Object
92
93
Pre-defined spring configurations for common animation styles.
94
95
```javascript { .api }
96
/**
97
* Pre-defined spring configuration presets
98
* Use these for common animation styles
99
*/
100
const presets = {
101
/** Default balanced preset - smooth with minimal bounce */
102
noWobble: { stiffness: 170, damping: 26 },
103
/** Gentle, slower animation with soft easing */
104
gentle: { stiffness: 120, damping: 14 },
105
/** More oscillation and bounce */
106
wobbly: { stiffness: 180, damping: 12 },
107
/** Quick, snappy animation with minimal overshoot */
108
stiff: { stiffness: 210, damping: 20 }
109
};
110
```
111
112
**Usage Examples:**
113
114
```javascript
115
import { spring, presets } from 'react-motion';
116
117
// Using presets
118
const gentleSpring = spring(100, presets.gentle);
119
const wobblySpring = spring(50, presets.wobbly);
120
const stiffSpring = spring(200, presets.stiff);
121
122
// Comparing presets in action
123
function PresetDemo() {
124
const [active, setActive] = useState(null);
125
126
const presetConfigs = [
127
{ name: 'noWobble', config: presets.noWobble },
128
{ name: 'gentle', config: presets.gentle },
129
{ name: 'wobbly', config: presets.wobbly },
130
{ name: 'stiff', config: presets.stiff }
131
];
132
133
return (
134
<div>
135
{presetConfigs.map(({ name, config }) => (
136
<Motion
137
key={name}
138
style={{
139
x: spring(active === name ? 200 : 0, config)
140
}}
141
>
142
{({ x }) => (
143
<div
144
style={{
145
transform: `translateX(${x}px)`,
146
padding: '10px',
147
margin: '5px 0',
148
background: '#007bff',
149
color: 'white',
150
cursor: 'pointer',
151
width: '200px'
152
}}
153
onClick={() => setActive(active === name ? null : name)}
154
>
155
{name}: stiffness={config.stiffness}, damping={config.damping}
156
</div>
157
)}
158
</Motion>
159
))}
160
</div>
161
);
162
}
163
```
164
165
### stripStyle Function
166
167
Utility function that extracts plain numeric values from style objects containing spring configurations.
168
169
```javascript { .api }
170
/**
171
* Extracts plain numeric values from spring-configured style objects
172
* @param style - Style object that may contain spring configurations
173
* @returns PlainStyle object with numeric values only
174
*/
175
function stripStyle(style/*: Style */)/*: PlainStyle */;
176
```
177
178
**Usage Examples:**
179
180
```javascript
181
import { stripStyle, spring } from 'react-motion';
182
183
// Style with springs
184
const styleWithSprings = {
185
x: spring(100, { stiffness: 120 }),
186
y: spring(200),
187
opacity: 1, // plain number
188
scale: spring(1.5, { damping: 20 })
189
};
190
191
// Extract plain values
192
const plainStyle = stripStyle(styleWithSprings);
193
// Result: { x: 100, y: 200, opacity: 1, scale: 1.5 }
194
195
// Useful for getting initial values
196
function MyComponent() {
197
const targetStyle = {
198
width: spring(expanded ? 300 : 100),
199
height: spring(expanded ? 200 : 50)
200
};
201
202
return (
203
<Motion
204
defaultStyle={stripStyle(targetStyle)} // Initial values without animation
205
style={targetStyle}
206
>
207
{interpolatedStyle => (
208
<div style={interpolatedStyle}>
209
Content
210
</div>
211
)}
212
</Motion>
213
);
214
}
215
```
216
217
## Spring Physics Explained
218
219
### Stiffness Parameter
220
221
Controls how quickly the spring tries to reach its target:
222
- **Low (60-120)**: Slower, more gentle animations
223
- **Medium (120-200)**: Balanced, natural feeling
224
- **High (200-300)**: Quick, snappy animations
225
226
```javascript
227
// Slow, gentle movement
228
spring(100, { stiffness: 80 })
229
230
// Quick, responsive movement
231
spring(100, { stiffness: 250 })
232
```
233
234
### Damping Parameter
235
236
Controls how much the spring oscillates around its target:
237
- **Low (8-15)**: More bounce and oscillation
238
- **Medium (15-30)**: Balanced with slight overshoot
239
- **High (30-50)**: Heavily damped, minimal overshoot
240
241
```javascript
242
// Bouncy animation
243
spring(100, { damping: 10 })
244
245
// Smooth with no overshoot
246
spring(100, { damping: 40 })
247
```
248
249
### Precision Parameter
250
251
Controls when the animation stops:
252
- **Smaller values (0.001-0.01)**: Animation runs longer, smoother ending
253
- **Larger values (0.1-1.0)**: Animation stops sooner, may feel abrupt
254
255
```javascript
256
// Very precise, runs until nearly perfect
257
spring(100, { precision: 0.001 })
258
259
// Less precise, stops when "close enough"
260
spring(100, { precision: 0.1 })
261
```
262
263
## Choosing Spring Parameters
264
265
### Common Combinations
266
267
```javascript
268
// UI Elements (buttons, menus)
269
spring(value, { stiffness: 300, damping: 30 })
270
271
// Layout changes (expanding panels)
272
spring(value, { stiffness: 120, damping: 17 })
273
274
// Playful interactions (hover effects)
275
spring(value, { stiffness: 180, damping: 12 })
276
277
// Smooth, professional (form transitions)
278
spring(value, { stiffness: 170, damping: 26 })
279
280
// Snappy mobile interactions
281
spring(value, { stiffness: 400, damping: 28 })
282
```
283
284
### Guidelines by Use Case
285
286
**Modal/Dialog Animations:**
287
```javascript
288
// Entry
289
{ stiffness: 300, damping: 30 }
290
// Exit
291
{ stiffness: 400, damping: 40 }
292
```
293
294
**List Item Transitions:**
295
```javascript
296
{ stiffness: 200, damping: 22 }
297
```
298
299
**Drag and Drop:**
300
```javascript
301
// While dragging
302
{ stiffness: 400, damping: 40 }
303
// Snap back
304
{ stiffness: 300, damping: 30 }
305
```
306
307
**Loading Animations:**
308
```javascript
309
{ stiffness: 150, damping: 15 } // Bouncy for attention
310
```
311
312
## Advanced Usage
313
314
### Conditional Spring Configs
315
316
```javascript
317
function AdaptiveSpring({ urgent, value }) {
318
const config = urgent
319
? { stiffness: 400, damping: 28 } // Fast for urgent changes
320
: { stiffness: 120, damping: 20 }; // Gentle for normal changes
321
322
return (
323
<Motion style={{ x: spring(value, config) }}>
324
{({ x }) => <div style={{ transform: `translateX(${x}px)` }} />}
325
</Motion>
326
);
327
}
328
```
329
330
### Dynamic Spring Parameters
331
332
```javascript
333
function DynamicSpring() {
334
const [distance, setDistance] = useState(0);
335
336
// Adjust stiffness based on distance
337
const stiffness = Math.max(120, Math.min(300, distance * 2));
338
339
return (
340
<Motion
341
style={{
342
x: spring(distance, { stiffness, damping: 20 })
343
}}
344
>
345
{({ x }) => (
346
<div
347
style={{ transform: `translateX(${x}px)` }}
348
onClick={(e) => setDistance(e.clientX)}
349
>
350
Click to move (stiffness: {stiffness})
351
</div>
352
)}
353
</Motion>
354
);
355
}
356
```
357
358
### Mixed Style Objects
359
360
```javascript
361
// Combining springs and static values
362
const mixedStyle = {
363
// Animated properties
364
x: spring(targetX, presets.stiff),
365
y: spring(targetY, presets.gentle),
366
scale: spring(targetScale),
367
368
// Static properties (no animation)
369
color: 'blue',
370
fontSize: 16,
371
fontWeight: 'bold'
372
};
373
```
374
375
## Performance Considerations
376
377
### Spring Calculation Cost
378
379
- More complex springs (lower precision) require more calculations
380
- High stiffness values may cause more frequent updates
381
- Consider using presets for optimal performance
382
383
### Animation Duration
384
385
Unlike CSS transitions, spring animations don't have fixed durations:
386
- Stiff springs with high damping finish quickly
387
- Soft springs with low damping take longer
388
- Very low precision values can cause unnecessarily long animations
389
390
### Memory Usage
391
392
- Each spring maintains internal state (position, velocity)
393
- Multiple springs on the same element share animation frames
394
- Springs automatically clean up when components unmount