Skip to content
All essays
WebMarch 27, 202512 min

Svelte Transitions and Animations

Create beautiful animations in Svelte. Learn transitions, keyframes, spring physics, and animation best practices.

Ü
Ümit Uz
Mobile & Full Stack Developer

Svelte provides powerful built-in tools for creating smooth transitions and animations with minimal code.

Built-in Transitions

Fade Transition

svelte
<script>
  import { fade } from 'svelte/transition';

  let visible = true;
</script>

<button on:click={() => visible = !visible}>
  Toggle
</button>

{#if visible}
  <div transition:fade>
    Fades in and out
  </div>
{/if}

Fly Transition

svelte
<script>
  import { fly } from 'svelte/transition';

  let visible = true;
</script>

{#if visible}
  <p transition:fly="{{ y: -200, duration: 1000 }}">
    Flies in from above
  </p>
{/if}

Slide Transition

svelte
<script>
  import { slide } from 'svelte/transition';

  let items = ['Item 1', 'Item 2', 'Item 3'];
</script>

{#each items as item, i (item)}
  <div transition:slide|local>
    {item}
  </div>
{/each}

Scale Transition

svelte
<script>
  import { scale } from 'svelte/transition';

  let visible = true;
</script>

{#if visible}
  <div transition:scale|global>
    Scales in and out
  </div>
{/if}

Transition Parameters

Common Parameters

svelte
<script>
  import { fade, fly } from 'svelte/transition';
  import { elasticOut } from 'svelte/easing';

  let visible = true;
</script>

{#if visible}
  <div
    transition:fade={{
      duration: 500,
      delay: 100,
      easing: elasticOut
    }}
  >
    Custom fade
  </div>

  <div
    transition:fly={{
      x: 100,
      y: 50,
      duration: 800,
      delay: 200
    }}
  >
    Custom fly
  </div>
{/if}

In and Out Transitions

svelte
<script>
  import { fade, fly } from 'svelte/transition';

  let visible = true;
</script>

{#if visible}
  <div
    in:fade={{ duration: 500 }}
    out:fly={{ y: 100 }}
  >
    Different transitions
  </div>
{/if}

Easing Functions

Built-in Easing

javascript
import {
  quad,
  cubic,
  quart,
  quint,
  sine,
  expo,
  circ,
  back,
  elastic
} from 'svelte/easing';

// Each has in, out, and inOut variants
const { elasticIn, elasticOut, elasticInOut } = elastic;

Custom Easing

javascript
// Custom bounce easing
function bounce(t) {
  if (t < 1 / 2.75) {
    return 7.5625 * t * t;
  } else if (t < 2 / 2.75) {
    return 7.5625 * (t -= 1.5 / 2.75) * t + 0.75;
  } else if (t < 2.5 / 2.75) {
    return 7.5625 * (t -= 2.25 / 2.75) * t + 0.9375;
  } else {
    return 7.5625 * (t -= 2.625 / 2.75) * t + 0.984375;
  }
}

Animations

Animate Directive

svelte
<script>
  import { animate } from 'svelte/motion';
  import { elasticOut } from 'svelte/easing';

  let items = [
    { id: 1, name: 'Item 1' },
    { id: 2, name: 'Item 2' },
    { id: 3, name: 'Item 3' }
  ];
</script>

<button on:click={() => items = items.reverse()}>
  Reverse
</button>

{#each items as item (item.id)}
  <div
    animate:flip={{
      duration: d => Math.sqrt(d * 200),
      easing: elasticOut
    }}
  >
    {item.name}
  </div>
{/each}

Flip Animation

svelte
<script>
  import { flip } from 'svelte/animate';

  let items = [1, 2, 3, 4, 5];

  function shuffle() {
    items = items.sort(() => Math.random() - 0.5);
  }
</script>

<button on:click={shuffle}>Shuffle</button>

<div class="container">
  {#each items as item (item)}
    <div animate:flip>{item}</div>
  {/each}
</div>

Spring Physics

Spring Store

svelte
<script>
  import { spring } from 'svelte/motion';

  const coords = spring({ x: 0, y: 0 }, {
    stiffness: 0.1,
    damping: 0.25
  });

  let size = spring(1);
</script>

<div
  style="transform: translate({$coords.x}px, {$coords.y}px) scale({$size})"
>
  Spring animation
</div>

<button on:click={() => size.set(2)}>Grow</button>
<button on:click={() => size.set(1)}>Shrink</button>

Spring Parameters

javascript
// Stiff spring
spring(value, { stiffness: 1, damping: 1 });

// Bouncy spring
spring(value, { stiffness: 0.1, damping: 0.25 });

// Precision
spring(value, { precision: 0.01 });

Tweened Values

svelte
<script>
  import { tweened } from 'svelte/motion';
  import { cubicOut } from 'svelte/easing';

  const progress = tweened(0, {
    duration: 1000,
    easing: cubicOut
  });

  function start() {
    progress.set(100);
  }
</script>

<div>{Math.round($progress)}%</div>
<button on:click={start}>Start</button>

Custom Transitions

Creating Custom Transitions

javascript
// transitions/glow.js
export function glow(node, { delay = 0, duration = 400 }) {
  return {
    delay,
    duration,
    css: (t, u) => {
      return `
        box-shadow: 0 0 ${t * 20}px rgba(0,0,0,0.5);
        transform: scale(${1 + t * 0.1});
      `;
    }
  };
}

export function blur(node, { delay = 0, duration = 400 }) {
  return {
    delay,
    duration,
    css: (t) => {
      return `filter: blur(${(1 - t) * 10}px);`;
    }
  };
}

Using Custom Transitions

svelte
<script>
  import { glow, blur } from '../transitions';

  let visible = true;
</script>

{#if visible}
  <div transition:glow>
    Glowing transition
  </div>

  <div transition:blur>
    Blur transition
  </div>
{/if}

Complex Animations

Staggered Animation

svelte
<script>
  import { fade } from 'svelte/transition';

  let items = [1, 2, 3, 4, 5];
</script>

{#each items as item, i (item)}
  <div
    transition:fade={{
      delay: i * 100,
      duration: 300
    }}
  >
    {item}
  </div>
{/each}

List Animation

svelte
<script>
  import { slide } from 'svelte/transition';

  let items = [];

  function addItem() {
    items = [...items, Date.now()];
  }

  function remove(item) {
    items = items.filter(i => i !== item);
  }
</script>

<button on:click={addItem}>Add</button>

{#each items as item (item)}
  <div transition:slide|local>
    {item}
    <button on:click={() => remove(item)}>Remove</button>
  </div>
{/each}

Animation Best Practices

  1. 1Use CSS transforms - More performant than layout changes
  2. 2Keep durations short - 200-500ms for most transitions
  3. 3Use appropriate easing - Match the feeling you want
  4. 4Test performance - Use DevTools to check frame rates
  5. 5Consider accessibility - Respect prefers-reduced-motion

Svelte's animation system makes it easy to create smooth, performant animations.

Related essays

Next essay
Svelte Actions: Reusable DOM Interactions