Learn Svelte in 3 minutes

Written by Rico Sta. Cruz
(@rstacruz) · 5 Aug 2022
I’ve been learning Svelte. Here are my notes as I learned it! If you’re already familiar with JavaScript and other frameworks, I’m hoping this guide can help you learn Svelte quickly. 👇

Svelte basics

Svelte is a web framework for writing rich user interfaces. Here’s a quick guide on Svelte 3.0.

Examples

The easiest way to learn Svelte (in my opinion) is the examples documentation. It’s comprehensive and straight-to-the-point.

Basic component

Svelte components store the markup, script and CSS styles in one .svelte file.

Example.svelte
<script>
let name = "Rico";
</script>
<div>
hello {name}!
</div>
<style>
div { color: dodgerblue; }
</style>

Nested components

Using export let will define a component property.

<script>
import Nested from './Nested.svelte';
</script>
<div>
My message is:
<Nested message="Hello there" />
</div>
Nested.svelte
<script>
export let message;
</script>
<div>
{message}
</div>
<style>
div { color: purple; }
</style>

Styling

Styles are scoped per component, but :global(…) will allow styling elements outside the component.

<p>
Only this will be red.
</p>
<style>
p { color: red; }
p :global(a) { color: blue; }
</style>

Attributes markup

Attributes are in HTML syntax, and can contain JavaScript expressions inside {…} brackets.

<img src={src}>
<img src="{src}">
<img src="https://{src}">
<img {src}> <!-- shorthand -->
<img {...props}> <!-- spread -->

State

State & events

Updating variables declared with let will trigger DOM updates.

<script>
let count = 0; // state
</script>
<button on:click={() => { count++ }}>
I was clicked {count} times
</button>

Computed state

Prefixing statements with $: will make it run with changes to the states it depends on.

<script>
let count;
// reactive state derived from `count`
$: doubled = count * 2;
</script>
6 collapsed lines
<button on:click={() => { count++ }}>
Count: {count}
</button>
<p>{count} * 2 = {doubled}</p>

Reactive statements

$: works with blocks too. Only values which directly appear within the $: block will become dependencies of the reactive statement.

<script>
// runs when the `title` prop changes
$: document.title = title;
// reactive block
$: {
console.log('title is', title);
}
</script>

Template syntax

If conditionals (#if)

{#if answer === 42}
Yes
{/if}

Else-if and else (:else)

{#if answer === 42 && a !== b}
Yes
{:else if answer === 74 || b > c}
Maybe
{:else}
No
{/if}

Loops (#each)

{#each items as item}
<li>{item.name} x {item.qty}</li>
{/each}
<!-- With index: -->
{#each items as item, index}
<li>{i + 1}: {item.name} x {item.qty}</li>
{/each}

Loops with keys

The key expression allows for efficient adding and removing of items.

{#each users as user (user.id)}
<UserCard {user} />
{/each}

Text markup

Text expressions are automatically escaped unless @html is used.

<p>{string}</p>
<p>{@html string}</p>

Forms

Text inputs

bind:value forms a two-way binding to a state variable.

<script>
let name = '';
</script>
<label>
Name:
<input bind:value={name} />
</label>
<p>Hello {name || 'stranger'}!</p>

Checkboxes

bind:checked binds the checked state of a checkbox to a state variable.

<script>
let subscribed = false;
</script>
<label>
<input bind:checked={subscribed} />
Subscribe to the newsletter
</label>
{#if subscribed}
<p>Thank you for subscribing!</p>
{/if}

Radio buttons

bind:group binds a variable to a group of elements, such as a radio button group.

<script>
let flavor;
</script>
<fieldset>
Flavor:
<input type='radio'
bind:group={flavor} value='vanilla'>
<input type='radio'
bind:group={flavor} value='mint'>
</fieldset>

Special components

Head elements

<svelte:head> allows inserting elements into the document head.

<svelte:head>
<meta name="robots" content="noindex">
</svelte:head>

Body events

<svelte:body> allows binding DOM events to the body element.

<svelte:body
on:mouseenter={handleMouseenter}
on:mouseleave={handleMouseleave}
use:someAction
/>

Window props

svelte:window allows manipulating window properties.

<svelte:window
bind:innerWidth={width}
/>
Properties
  • innerWidth
  • innerHeight
  • outerWidth
  • outerHeight
  • scrollX (rw)
  • scrollY (rw)
  • online

Window events

<svelte:window> also allows binding DOM events to the window object.

<svelte:window
on:keydown={handleKeydown}
/>

Slots

Slots

Slots allow passing content to a component (“children”).

<script>
import Notice from './Notice.svelte'
</script>
<Notice>
There will be rain today.
</Notice>
Notice.svelte
<div class='notice'>
<strong>Notice:</strong>
<slot></slot>
</div>

Named slots

Use named slots to pass more than 1 group of children elements.

<MyDialog>
<h1 slot='header'>Forecast:</h1>
There will be rain today.
<div slot='footer'>23°C, Rain</div>
</MyDialog>
MyDialog.svelte
<dialog class='my-dialog'>
<header>
<slot name='header'></slot>
</header>
<slot></slot>
<footer>
<slot name='footer'></slot>
</footer>
</dialog>

Fragments in named slots

<svelte:fragment slot="items">
<li>Apple</li>
<li>Banana</li>
<li>Cherry</li>
</svelte:fragment>
<slot name="items"></slot>

Slot props

<slot prop={value}></slot>

Slot fallbacks

<slot prop={value}>
This is fallback content
</slot>

Other features

bind:this

<script>
import { onMount } from 'svelte';
let canvasEl;
onMount(() => {
drawOn(canvasEl.getContext('2d'));
});
</script>
<canvas bind:this={canvasEl}></canvas>

Docs: bind:this

Written by Rico Sta. Cruz

I am a web developer helping make the world a better place through JavaScript, Ruby, and UI design. I write articles like these often. If you'd like to stay in touch, subscribe to my list.

Comments

More articles

← More articles