Svelte hat Animationen für ein- und ausblendende Elemente direkt eingebaut — ohne externe Library, ohne CSS-Frickelei. Du schreibst transition:fade an ein Element, und sobald es im DOM auftaucht oder verschwindet, fadet Svelte es automatisch ein oder aus. Dieser Artikel erklärt das Grundprinzip, die drei Direktiven (transition:, in:, out:) und stellt alle sechs eingebauten Helfer aus dem Modul svelte/transition mit Beispielen vor.
Das Grundprinzip
Eine Transition ist eine Animation, die läuft, wenn ein Element ins DOM eingefügt oder entfernt wird. Sie braucht zwei Zutaten:
- Ein Block oder eine Bedingung, die das Element bedingt rendert (z. B.
{#if},{#each}oder ein Komponentenwechsel). - Eine
transition:-Direktive mit einem Transitions-Helfer.
<script>
import { fade } from 'svelte/transition';
let visible = $state(true);
</script>
<button onclick={() => visible = !visible}>Toggle</button>
{#if visible}
<p transition:fade>
Ich fade mich ein und aus.
</p>
{/if}Wenn visible von false auf true wechselt, fadet <p> ein. Beim Wechsel zurück fadet es aus, bevor es entfernt wird. Du musst nichts manuell triggern.
Drei Direktiven: transition:, in:, out:
Svelte bietet drei Direktiven für unterschiedliche Anwendungsfälle:
| Direktive | Verhalten |
|---|---|
transition:fn | Läuft beim Einblenden und beim Ausblenden. |
in:fn | Läuft nur beim Einblenden. |
out:fn | Läuft nur beim Ausblenden. |
in: und out: lassen sich kombinieren — z. B. anders einblenden als ausblenden:
<script>
import { fly, fade } from 'svelte/transition';
let visible = $state(true);
</script>
{#if visible}
<p in:fly={{ y: 20 }} out:fade>
Fliege rein, fade raus.
</p>
{/if}Wann das nützlich ist: Eine Toast-Nachricht soll spektakulär einfliegen, aber unauffällig verschwinden. Mit in: und out: getrennt.
Parameter setzen
Jeder Transitions-Helfer akzeptiert ein Parameter-Objekt. Drei Parameter sind allen gemeinsam:
| Parameter | Bedeutung |
|---|---|
delay | Wartezeit in Millisekunden vor Start. |
duration | Dauer der Animation in Millisekunden. |
easing | Easing-Funktion (Zeit-zu-Fortschritt-Mapping). |
<script>
import { fade } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
let visible = $state(true);
</script>
{#if visible}
<p transition:fade={{ duration: 600, easing: quintOut, delay: 100 }}>
Sanft.
</p>
{/if}Easing-Funktionen kommen aus dem Modul svelte/easing — eine Sammlung typischer Verläufe (linear, cubicOut, quintInOut, bounceOut, …). Defaults gibt es für jeden Helfer, du musst nichts überschreiben.
fade – Opazität
Der Klassiker: Element fadet von 0 auf seine normale Opazität (beim Einblenden) und zurück.
<script>
import { fade } from 'svelte/transition';
let visible = $state(true);
</script>
{#if visible}
<div transition:fade={{ duration: 300 }}>Hallo</div>
{/if}Eingebaute Defaults: delay: 0, duration: 400. Eigene Parameter:
| Parameter | Beschreibung |
|---|---|
delay | Verzögerung |
duration | Dauer |
easing | Easing-Funktion |
fly – Position + Opazität
Bewegt das Element von einer angegebenen x/y-Verschiebung zur Endposition (beim Einblenden) und zurück.
<script>
import { fly } from 'svelte/transition';
let visible = $state(true);
</script>
{#if visible}
<div transition:fly={{ x: 200, duration: 400 }}>
Komme von rechts.
</div>
{/if}x: 200 bedeutet: 200 Pixel rechts von der Endposition starten und reinfliegen. y: -50 heißt: 50 Pixel oberhalb starten und nach unten in die Endposition fliegen.
| Parameter | Beschreibung |
|---|---|
x | Horizontale Verschiebung |
y | Vertikale Verschiebung |
opacity | Start-Opazität (Default 0) |
delay, duration, easing | wie üblich |
slide – Höhe oder Breite kollabieren
slide animiert die Größe des Elements von 0 auf seine natürliche Größe — typisch für Aufklapp-Menüs oder Akkordeons:
<script>
import { slide } from 'svelte/transition';
let open = $state(false);
</script>
<button onclick={() => open = !open}>Mehr</button>
{#if open}
<div transition:slide>
Aufgeklappter Inhalt.
</div>
{/if}Standardmäßig wird die Höhe (Y-Achse) animiert. Mit axis: 'x' wird stattdessen die Breite animiert.
| Parameter | Beschreibung |
|---|---|
axis | 'y' (Default) oder 'x' |
delay, duration, easing | wie üblich |
scale – Zoom-Effekt
scale animiert das Element von einem kleineren start-Wert auf 1 (volle Größe).
<script>
import { scale } from 'svelte/transition';
let visible = $state(true);
</script>
{#if visible}
<div transition:scale={{ start: 0.7, duration: 250 }}>
Pop!
</div>
{/if}| Parameter | Beschreibung |
|---|---|
start | Start-Skalierung (Default 0) |
opacity | Start-Opazität (Default 0) |
delay, duration, easing | wie üblich |
blur – Unscharf rein und raus
blur kombiniert einen CSS-filter: blur(...) mit Opazität:
<script>
import { blur } from 'svelte/transition';
let visible = $state(true);
</script>
{#if visible}
<h1 transition:blur={{ amount: 10 }}>
Unscharf rein.
</h1>
{/if}| Parameter | Beschreibung |
|---|---|
amount | Maximaler Blur in Pixel (Default 5) |
opacity | Start-Opazität (Default 0) |
delay, duration, easing | wie üblich |
draw – SVG-Pfade animieren
draw ist speziell für SVG-Pfade gedacht. Es zeichnet einen Pfad „in der Luft” von Anfang bis Ende — typisch für Logo-Animations und Diagramme.
<script>
import { draw } from 'svelte/transition';
let visible = $state(true);
</script>
<svg viewBox="0 0 100 100" width="200" height="200">
{#if visible}
<path
d="M10,50 Q50,10 90,50 T170,50"
stroke="teal"
fill="none"
stroke-width="2"
transition:draw={{ duration: 1500 }}
/>
{/if}
</svg>Das Element muss getTotalLength() unterstützen (also ein SVG-<path>, <line> o. ä.).
| Parameter | Beschreibung |
|---|---|
speed | Pixel pro Sekunde (statt fester duration) |
delay, duration, easing | wie üblich |
Reduced Motion respektieren
Manche Nutzer haben „Bewegungen reduzieren” im Betriebssystem aktiviert (Barrierefreiheit). Animationen können dann übel werden — Schwindel, Kopfschmerzen. Svelte berücksichtigt das nicht automatisch — du tust es selbst:
<script>
import { fade } from 'svelte/transition';
const reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const fadeOptions = reduced ? { duration: 0 } : { duration: 300 };
</script>
{#if visible}
<p transition:fade={fadeOptions}>Hallo</p>
{/if}Bei aktivierter Einstellung ist die Transition praktisch instant — der visuelle Effekt entfällt, das Verhalten bleibt erhalten.
Häufige Stolperfallen
Transition feuert nicht beim ersten Mount.
Per Default lösen Transitions nicht beim initialen Mount der Komponente aus — nur bei Veränderungen danach. Wenn du das ändern willst, gibt es <svelte:options> mit globalIntroSync oder das intro: true-Setting im Render-Aufruf.
Element verschwindet, bevor Transition fertig ist.
Ein {#if}, das erst rendert, wenn die Transition läuft, kann zu unschönem Flicker führen. Mit out:-Parameter duration: 0 lässt sich das vermeiden, falls Out-Animation nicht gewünscht ist.
Vergessenes Importieren.
fade, fly etc. müssen aus svelte/transition importiert werden. Ohne Import gibt es einen Compile-Fehler.
Pfade ohne getTotalLength().
draw funktioniert nur auf SVG-Elementen mit gemessener Länge. Auf <rect> oder <polygon> ohne Stroke-Path geht es nicht.
Transitions in tief verschachtelten {#each}-Blöcken.
Bei vielen gleichzeitig animierten Elementen kann die Performance leiden. In dem Fall lieber CSS-Animationen nutzen oder nur einzelne Transitions setzen.