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

Classes are particularly useful when you need to validate data. In the case of this Box class, it shouldn’t be possible to keep embiggening past the maximum allowed by the sliders, but that’s exactly what happens.

We can fix that by replacing width and height with getters and setters, otherwise known as accessors. First, convert them to private properties:

App
class Box {
	#width = $state(0);
	#height = $state(0);
	area = $derived(this.#width * this.#height);

	constructor(width, height) {
		this.#width = width;
		this.#height = height;
	}

	// ...
}

Then, create some getters and setters:

App
class Box {
	// ...

	get width() {
		return this.#width;
	}

	get height() {
		return this.#height;
	}

	set width(value) {
		this.#width = value;
	}

	set height(value) {
		this.#height = value;
	}

	embiggen(amount) {
		this.width += amount;
		this.height += amount;
	}
}

Finally, add the validation to the setters:

App
set width(value) {
	this.#width = Math.max(0, Math.min(MAX_SIZE, value));
}

set height(value) {
	this.#height = Math.max(0, Math.min(MAX_SIZE, value));
}

It’s now impossible to increase the box size past safe limits, whether through the bind:value on the range inputs, or the embiggen method, no matter how hard you press the button.

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
<script>
	const MAX_SIZE = 200;
 
	class Box {
		width = $state(0);
		height = $state(0);
		area = $derived(this.width * this.height);
 
		constructor(width, height) {
			this.width = width;
			this.height = height;
		}
 
		embiggen(amount) {
			this.width += amount;
			this.height += amount;
		}
	}
 
	const box = new Box(100, 100);
</script>
 
<label>
	<input type="range" bind:value={box.width} min={0} max={MAX_SIZE} />
	{box.width}
</label>
 
<label>
	<input type="range" bind:value={box.height} min={0} max={MAX_SIZE} />
	{box.height}
</label>
 
<button onclick={() => box.embiggen(10)}>embiggen</button>
 
<hr>
 
<div
	class="box"
	style:width="{box.width}px"
	style:height="{box.height}px"
>
	{box.area}
</div>
 
<style>
	label {
		display: flex;
		align-items: center;
	}
 
	hr {
		margin: 1em 0;
		border: none;
		border-bottom: 1px solid #888;
	}
 
	.box {
		background: radial-gradient(at 25% 25%, hsl(15 100 60), hsl(15 100 50)) ;
		border-radius: 2px;
		filter: drop-shadow(0 0 10px hsl(15 100 50 / 0.3));
		display: flex;
		align-items: center;
		justify-content: center;
		overflow: hidden;
	}
</style>