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

You can bind to properties of <audio> and <video> elements, making it easy to (for example) build custom player UI, like AudioPlayer.svelte.

First, add the <audio> element along with its bindings (we’ll use the shorthand form for src, duration and paused):

AudioPlayer
<div class="player" class:paused>
	<audio
		{src}
		bind:currentTime={time}
		bind:duration
		bind:paused
	></audio>

	<button
		class="play"
		aria-label={paused ? 'play' : 'pause'}
	></button>

Next, add an event handler to the <button> that toggles paused:

AudioPlayer
<button
	class="play"
	aria-label={paused ? 'play' : 'pause'}
	onclick={() => paused = !paused}
></button>

Our audio player now has basic functionality. Let’s add the ability to seek to a specific part of a track by dragging the slider. Inside the slider’s pointerdown handler there’s a seek function, where we can update time:

AudioPlayer
function seek(e) {
	const { left, width } = div.getBoundingClientRect();

	let p = (e.clientX - left) / width;
	if (p < 0) p = 0;
	if (p > 1) p = 1;

	time = p * duration;
}

When the track ends, be kind — rewind:

AudioPlayer
<audio
	{src}
	bind:currentTime={time}
	bind:duration
	bind:paused
	onended={() => {
		time = 0;
	}}
></audio>

The complete set of bindings for <audio> and <video> is as follows — seven readonly bindings...

  • duration — the total duration, in seconds
  • buffered — an array of {start, end} objects
  • seekable — ditto
  • played — ditto
  • seeking — boolean
  • ended — boolean
  • readyState — number between (and including) 0 and 4

...and five two-way bindings:

  • currentTime — the current position of the playhead, in seconds
  • playbackRate — speed up or slow down (1 is ‘normal’)
  • paused — this one should be self-explanatory
  • volume — a value between 0 and 1
  • muted — a boolean value where true is muted

Videos additionally have readonly videoWidth and videoHeight bindings.

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
<script>
	import AudioPlayer from './AudioPlayer.svelte';
	import { tracks } from './tracks.js';
</script>
 
<div class="centered">
	{#each tracks as track}
		<AudioPlayer {...track} />
	{/each}
</div>
 
<style>
	.centered {
		display: flex;
		flex-direction: column;
		height: 100%;
		justify-content: center;
		gap: 0.5em;
		max-width: 40em;
		margin: 0 auto;
	}
</style>