Skip to main content
Basic Svelte
Introduction
Reactivity
Props
Logic
Events
Bindings
Classes and styles
Actions
Transitions
Advanced Svelte
Advanced reactivity
Reusing content
Motion
Advanced bindings
Advanced transitions
Context API
Special elements
<script module>
Next steps
Basic SvelteKit
Introduction
Routing
Loading data
Headers and cookies
Shared modules
Forms
API routes
$app/state
Errors and redirects
Advanced SvelteKit
Hooks
Page options
Link options
Advanced routing
Advanced loading
Environment variables
Conclusion

The Spring class is an alternative to Tween that often works better for values that are frequently changing.

In this example we have a circle that follows the mouse, and two values — the circle’s coordinates, and its size. Let’s convert them to springs:

App
<script>
	import { Spring } from 'svelte/motion';

	let coords = new Spring({ x: 50, y: 50 });
	let size = new Spring(10);
</script>
<script lang="ts">
	import { Spring } from 'svelte/motion';

	let coords = new Spring({ x: 50, y: 50 });
	let size = new Spring(10);
</script>

As with Tween, springs have a writable target property and a readonly current property. Update the event handlers...

<svg
	onmousemove={(e) => {
		coords.target = { x: e.clientX, y: e.clientY };
	}}
	onmousedown={() => (size.target = 30)}
	onmouseup={() => (size.target = 10)}
	role="presentation"
>

...and the <circle> attributes:

<circle
	cx={coords.current.x}
	cy={coords.current.y}
	r={size.current}
></circle>

Both springs have default stiffness and damping values, which control the spring’s, well... springiness. We can specify our own initial values:

App
let coords = new Spring({ x: 50, y: 50 }, {
	stiffness: 0.1,
	damping: 0.25
});

Waggle your mouse around, and try dragging the sliders to get a feel for how they affect the spring’s behaviour. Notice that you can adjust the values while the spring is still in motion.

Edit this page on GitHub

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
<script>
	let coords = $state({ x: 50, y: 50 });
	let size = $state(10);
</script>
 
<svg
	onmousemove={(e) => {
		coords = { x: e.clientX, y: e.clientY };
	}}
	onmousedown={() => (size = 30)}
	onmouseup={() => (size = 10)}
	role="presentation"
>
	<circle
		cx={coords.x}
		cy={coords.y}
		r={size}
	></circle>
</svg>
 
<div class="controls">
	<label>
		<h3>stiffness ({coords.stiffness})</h3>
		<input
			bind:value={coords.stiffness}
			type="range"
			min="0.01"
			max="1"
			step="0.01"
		/>
	</label>
 
	<label>
		<h3>damping ({coords.damping})</h3>
		<input
			bind:value={coords.damping}
			type="range"
			min="0.01"
			max="1"
			step="0.01"
		/>
	</label>
</div>
 
<style>
	svg {
		position: absolute;
		width: 100%;
		height: 100%;
		left: 0;
		top: 0;
	}
 
	circle {
		fill: #ff3e00;
	}
 
	.controls {
		position: absolute;
		top: 1em;
		right: 1em;
		width: 200px;
		user-select: none;
	}
 
	.controls input {
		width: 100%;
	}
</style>