Svelte Transitions & Animations
Svelte makes it easy to add smooth transitions and animations to your app with built-in transition directives.
Built-in Transitions
<script>
import { fade, fly, slide, scale, blur, draw } from 'svelte/transition';
import { quintOut } from 'svelte/easing';
let visible = true;
</script>
<!-- Fade -->
{#if visible}
<p transition:fade>Fades in and out</p>
{/if}
<!-- Fly -->
{#if visible}
<p transition:fly="{{ y: 200, duration: 500 }}">Flies in from below</p>
{/if}
<!-- Slide -->
{#if visible}
<p transition:slide>Slides in and out</p>
{/if}
<!-- Scale -->
{#if visible}
<p transition:scale="{{ start: 0, duration: 500, easing: quintOut }}">
Scales in and out
</p>
{/if}
<!-- Separate in and out transitions -->
{#if visible}
<p in:fly="{{ y: 200 }}" out:fade>Different transitions</p>
{/if}
<!-- Local transitions (don't play on initial render) -->
{#if visible}
<p transition:fade|local>Only when toggled, not on mount</p>
{/if}
<button on:click={() => visible = !visible}>Toggle</button>Custom Transitions
<script>
function customTransition(node, { duration = 400 }) {
return {
duration,
css: t => {
const eased = quintOut(t);
return `
opacity: ${eased};
transform: scale(${eased}) rotate(${eased * 360}deg);
`;
}
};
}
// JavaScript-based transition
function typewriter(node, { speed = 50 }) {
const text = node.textContent;
const duration = text.length * speed;
return {
duration,
tick: t => {
const i = Math.trunc(text.length * t);
node.textContent = text.slice(0, i);
}
};
}
</script>
{#if visible}
<p transition:customTransition>Custom transition</p>
<p in:typewriter="{{ speed: 30 }}">Typing effect...</p>
{/if}Animations
<script>
import { flip } from 'svelte/animate';
import { quintOut } from 'svelte/easing';
let todos = [
{ id: 1, text: 'Todo 1', done: false },
{ id: 2, text: 'Todo 2', done: false }
];
function remove(id) {
todos = todos.filter(t => t.id !== id);
}
</script>
<!-- Animate list reordering -->
{#each todos as todo (todo.id)}
<div animate:flip="{{ duration: 300, easing: quintOut }}">
{todo.text}
<button on:click={() => remove(todo.id)}>×</button>
</div>
{/each}Motion (Tweened & Spring)
<script>
import { tweened } from 'svelte/motion';
import { spring } from 'svelte/motion';
import { cubicOut } from 'svelte/easing';
// Tweened - smooth interpolation
const progress = tweened(0, {
duration: 400,
easing: cubicOut
});
// Spring - physics-based motion
const coords = spring(
{ x: 0, y: 0 },
{
stiffness: 0.1,
damping: 0.25
}
);
function setProgress(value) {
progress.set(value);
}
</script>
<progress value={$progress} max="100"></progress>
<button on:click={() => setProgress(100)}>Complete</button>
<!-- Follow mouse with spring -->
<svg on:mousemove={(e) => coords.set({ x: e.clientX, y: e.clientY })}>
<circle cx={$coords.x} cy={$coords.y} r="10" />
</svg>Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free