Svelte Cheat Sheet
A concise guide to Svelte 5 runes, reactive state, template syntax, and stores for building fast, compiler-driven components.
Reactive State with Runes
Svelte 5's rune-based reactivity: state, derived values, and effects.
<script> let count = $state(0); let doubled = $derived(count * 2); $effect(() => { console.log(`count is now ${count}`); }); function increment() { count += 1; }</script><button onclick={increment}> Count: {count} (doubled: {doubled})</button>
Template Control Flow
Conditional blocks, loops, and two-way binding.
{#if user} <p>Welcome, {user.name}</p>{:else} <p>Please log in</p>{/if}{#each items as item (item.id)} <li>{item.name}</li>{/each}<input bind:value={name} /><button onclick={() => count++}>+1</button>
Core Concepts
The building blocks of a modern Svelte 5 component.
- $state- creates reactive state; reassigning it triggers a UI update
- $derived- a computed value automatically recalculated when its dependencies change
- $props- declares a component's props, replacing the legacy 'export let' syntax
- $effect- runs a side effect whenever the reactive values it reads change
- bind:value- two-way binds a form element to a variable
- {#each}- loop block for rendering lists, supports an optional keyed expression
- {#if}/{:else if}/{:else}- conditional rendering blocks
- {#snippet}- defines a reusable chunk of markup, replacing many slot use cases
Stores
Sharing reactive state across components with svelte/store.
// store.jsimport { writable, derived } from 'svelte/store';export const count = writable(0);export const doubled = derived(count, ($count) => $count * 2);// Component.svelte<script> import { count } from './store.js';</script><button onclick={() => $count++}> {$count}</button>
Transitions & Flip Animations
Animate elements entering, leaving, and reordering the DOM.
<script> import { fade, fly } from 'svelte/transition'; import { flip } from 'svelte/animate'; import { quintOut } from 'svelte/easing'; let items = $state([1, 2, 3]);</script>{#if visible} <div transition:fade={{ duration: 200 }}>Fades in and out</div>{/if}<div in:fly={{ y: -20, duration: 300 }} out:fade> Different in/out transitions</div>{#each items as item (item)} <div animate:flip={{ duration: 250, easing: quintOut }}> {item} </div>{/each}
Two-Way Bindable Props
Opt a prop into two-way binding from a parent using $bindable().
<!-- Slider.svelte --><script> let { value = $bindable(0), min = 0, max = 100 } = $props();</script><input type="range" {min} {max} bind:value /><!-- Parent.svelte --><script> let volume = $state(50);</script><Slider bind:value={volume} /><p>Current volume: {volume}</p>
Custom Actions (use:)
Reusable, imperative element behavior with lifecycle and reactive params.
// clickOutside.jsexport function clickOutside(node, callback) { function handleClick(event) { if (node && !node.contains(event.target)) { callback(); } } document.addEventListener('click', handleClick, true); return { update(newCallback) { callback = newCallback; }, destroy() { document.removeEventListener('click', handleClick, true); } };}// Component.svelte<script> import { clickOutside } from './clickOutside.js'; let open = $state(true);</script><div use:clickOutside={() => (open = false)}>Menu</div>
Snippets & {@render}
Pass reusable markup fragments as props, replacing most slot use cases.
<!-- List.svelte --><script> let { items, row } = $props();</script><ul> {#each items as item} <li>{@render row(item)}</li> {/each}</ul><!-- Parent.svelte -->{#snippet row(item)} <strong>{item.name}</strong> - {item.price}{/snippet}<List {items} {row} />
Advanced Rune & Reactivity APIs
Lesser-known runes and helpers for fine-grained control over reactivity.
- $state.raw- opts an object/array out of deep reactivity; only reassignment triggers updates, useful for large immutable data
- $state.snapshot- takes a plain, non-proxied snapshot of a reactive state object, e.g. for console.log or structuredClone
- untrack- reads a reactive value inside $effect/$derived without registering it as a dependency
- $effect.pre- runs before the DOM updates, useful for measuring layout before a change is applied
- $effect.root- creates a non-tracked scope for manually created effects outside component initialization
- $inspect- development-only rune that logs a value and re-logs whenever it changes
- <script module>- module-level script shared across all instances of a component, replaces the old context='module'
- $host()- inside a custom element component, returns the host element for dispatching native DOM events
In Svelte 5, prefer runes ($state, $derived, $effect) over the legacy 'let'/'$:' reactivity -- they work consistently both inside .svelte files and in plain .svelte.js modules, and they make reactive dependencies explicit instead of inferred.