Bedingtes Rendern in Svelte erledigt der {#if}-Block. Im Gegensatz zu JSX-Frameworks wie React, wo Bedingungen über JavaScript-Ausdrücke (condition && <Comp />) ausgedrückt werden, hat Svelte dafür eine eigene Syntax. Sie ist kompakter, deckt else if und else direkt ab und macht das Template übersichtlicher. Dieser Artikel zeigt alle Varianten und typische Patterns.
Grundsyntax
<script>
let isLoggedIn = $state(false);
</script>
{#if isLoggedIn}
<p>Willkommen zurück!</p>
{/if}{#if expr} öffnet einen Block, {/if} schließt ihn. Wenn expr truthy ist, wird der Inhalt gerendert.
else und else if
{#if isLoggedIn}
<p>Willkommen zurück!</p>
{:else}
<p>Bitte einloggen.</p>
{/if}{#if score >= 90}
<p>Sehr gut</p>
{:else if score >= 70}
<p>Gut</p>
{:else if score >= 50}
<p>Befriedigend</p>
{:else}
<p>Nicht bestanden</p>
{/if}Beachten: {:else} und {:else if} mit Doppelpunkt. Es ist das Svelte-Konstrukt zur Fortsetzung eines offenen Blocks.
Verschachtelte Bedingungen
Blöcke lassen sich beliebig schachteln:
{#if user}
{#if user.isAdmin}
<AdminPanel />
{:else}
<p>Hallo, {user.name}</p>
{/if}
{:else}
<p>Bitte einloggen</p>
{/if}Bei zu tiefen Schachtelungen lohnt es sich, die Logik mit $derived oder eigenen Komponenten zu kapseln:
<script>
let view = $derived(
!user ? 'guest' :
user.isAdmin ? 'admin' : 'member'
);
</script>
{#if view === 'guest'}
<p>Bitte einloggen</p>
{:else if view === 'admin'}
<AdminPanel />
{:else}
<p>Hallo, {user.name}</p>
{/if}if ohne Block – kurze Variante per Ausdruck
Einzeilige Bedingungen lassen sich in Text-Expressions auch mit Operator-Logik schreiben — wie in JSX:
<p>{user ? `Hallo, ${user.name}` : 'Bitte einloggen'}</p>Für reine Text-Ausgaben oft kürzer als ein {#if}-Block. Sobald Markup im Spiel ist, ist {#if} lesbarer.
Vergleich zu JSX
JSX-Pattern und ihre Svelte-Entsprechungen:
JSX: Svelte:
---- -------
{cond && <X />} {#if cond}<X />{/if}
{cond ? <A /> : <B />} {#if cond}<A />{:else}<B />{/if}
Ternary mit fallback null {#if cond}<X />{/if}
IIFE für komplexe Logik $derived + {#if}/{:else if}Svelte-Bedingungen sind deklarativ als eigenes Konstrukt, nicht als Ausdruck. Das ist ein bewusster Stil-Unterschied.
State-Reset bei Bedingungen
Wenn ein {#if}-Block einen Wechsel von wahr zu falsch und zurück erlebt, wird der Inhalt vollständig zerstört und neu gemountet. Lokaler State ($state innerhalb der Komponente, DOM-Refs) wird verworfen.
<script>
let visible = $state(true);
</script>
<button onclick={() => visible = !visible}>Toggle</button>
{#if visible}
<Counter /> <!-- Counter-State wird beim erneuten Show resettet -->
{/if}Wenn der State erhalten bleiben soll, halte die Komponente immer im DOM und steuere die Sichtbarkeit per CSS:
<Counter style:display={visible ? 'block' : 'none'} />Typeguards in TypeScript
In TypeScript-Dateien helfen {#if}-Blöcke beim Narrowing — der Compiler weiß im inneren Block, dass die geprüfte Variable nicht null/undefined ist:
<script lang="ts">
type Props = { user?: { name: string } };
let { user }: Props = $props();
</script>
{#if user}
<!-- Innerhalb: user ist definiert -->
<p>{user.name}</p>
{/if}Innerhalb des Blocks ist user als { name: string } typisiert — das ? aus dem äußeren Type ist eliminiert.
Häufige Stolperfallen
if als JS-Statement im Markup.
{if condition}<p>Text</p>{/if}# ist Pflicht: {#if condition}. Ohne # interpretiert Svelte das als Ausdruck.
Fehlendes {/if}.
Compiler-Fehler. Svelte-Blöcke müssen explizit geschlossen werden — anders als bei JSX-Ternaries.
condition && <Comp />-Pattern aus React kopiert.
In Svelte-Markup gibt es das nicht direkt. Im Inneren einer Expression ({...}) kann man es nutzen, aber kanonisch ist {#if}.
Falsy-Werte wie 0.
{#if items.length}
<ul>...</ul>
{/if}
<!-- bei items.length === 0: nichts gerendert -->0, '' und null/undefined sind in Svelte (wie überall) falsy. Bei length-Prüfung explizit > 0 schreiben, falls die Absicht klarer sein soll.