{#if}
{#if} conditionally renders markup. {:else if} and {:else} chain; {:then} / {:catch} shape {#await}; {@const} introduces a local for the block.
Conditional patterns
EXAMPLE
<script>
let user = $state(null);
let posts = $state([]);
let promise = fetchUser();
</script>
<!-- 1) Basic if / else if / else -->
{#if user?.role === 'admin'}
<AdminTools />
{:else if user}
<p>Hi, {user.name}</p>
{:else}
<SignIn />
{/if}
<!-- 2) Empty list fallback inside #each — Svelte's killer feature -->
<ul>
{#each posts as p (p.id)}
<li>{p.title}</li>
{:else}
<li class="empty">No posts yet.</li>
{/each}
</ul>
<!-- 3) #await — async data with loading / error states -->
{#await promise}
<Spinner />
{:then user}
<p>{user.name}</p>
{:catch err}
<ErrorBanner message={err.message} />
{/await}
<!-- Shorter form — no loading state -->
{#await api.get('/me') then user}
<p>{user.email}</p>
{/await}
<!-- 4) #key — re-mount the subtree when the key changes -->
{#key route.path}
<PageWithLocalState />
{/key}
<!-- 5) Local const inside a block -->
{#each users as user}
{@const initials = user.name.split(' ').map(p => p[0]).join('')}
<Avatar {initials} />
{/each}
<!-- 6) Snippets (Svelte 5) — reusable blocks of markup -->
{#snippet row(p)}
<li><a href="/posts/{p.id}">{p.title}</a></li>
{/snippet}
<ul>{#each posts as p}{@render row(p)}{/each}</ul>
Why it matters
{#each … :else} is Svelte’s elegant answer to the empty-list problem. Most frameworks need a wrapper if; Svelte ships it as part of the loop.
Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.
Example
Exercise
Conditional block.
{
user}Hi {user.name}{/if}
Begins with #.
Discussion
Loading…