0
0
Svelteframework~15 mins

Custom transitions in Svelte - Deep Dive

Choose your learning style9 modes available
Overview - Custom transitions
What is it?
Custom transitions in Svelte let you create smooth animations when elements enter or leave the page. Instead of using fixed animations, you write your own code to control how elements appear or disappear. This helps make your app feel lively and unique. You can define exactly how properties like position, size, or opacity change over time.
Why it matters
Without custom transitions, web pages feel static and boring. They lack personality and can confuse users when elements suddenly appear or vanish. Custom transitions solve this by making changes feel natural and clear, improving user experience. They also let developers express brand style and creativity, making apps stand out.
Where it fits
Before learning custom transitions, you should know basic Svelte components and how to use built-in transitions. After mastering custom transitions, you can explore advanced animation libraries or combine transitions with state management for dynamic interfaces.
Mental Model
Core Idea
A custom transition is a function that smoothly changes an element's style properties over time when it enters or leaves the DOM.
Think of it like...
Imagine a curtain slowly opening or closing on a stage. You control how fast it moves and how it looks while moving, making the reveal or hide feel natural and intentional.
┌───────────────────────────────┐
│ Element enters or leaves DOM   │
├─────────────┬─────────────────┤
│ Svelte calls│ Custom function │
│ transition  │ that returns    │
│ hook       │ style changes   │
├─────────────┴─────────────────┤
│ Over time, styles update smoothly│
│ until transition ends           │
└───────────────────────────────┘
Build-Up - 7 Steps
1
FoundationWhat is a transition in Svelte
🤔
Concept: Transitions animate elements when they enter or leave the page.
In Svelte, a transition is a way to animate an element's appearance or disappearance. For example, the built-in fade transition changes opacity from 0 to 1 when an element appears, and back when it disappears. You use it by adding `transition:fade` to an element.
Result
Elements smoothly fade in or out instead of appearing or disappearing instantly.
Understanding that transitions control element visibility changes helps you see how animations improve user experience.
2
FoundationUsing built-in transitions
🤔
Concept: Svelte provides ready-made transitions like fade, slide, and scale.
You import transitions from 'svelte/transition' and apply them with `transition:name`. For example: {#if show}

Hello!

{/if} This fades the paragraph in and out when toggled.
Result
The paragraph smoothly appears and disappears with a fade effect.
Knowing built-in transitions gives you a quick way to add polish before creating your own.
3
IntermediateCreating a custom transition function
🤔Before reading on: do you think a custom transition needs to return a function or an object? Commit to your answer.
Concept: A custom transition is a function that returns an object describing how styles change over time.
A custom transition function receives parameters like node (the element), duration, and easing. It returns an object with a `css` function that receives a progress value `t` from 0 to 1. This function returns a CSS string describing styles at that moment. Example: function customFade(node, { duration = 400 }) { return { duration, css: t => `opacity: ${t}` }; } Use it with `transition:customFade`.
Result
Elements fade in and out using your custom function instead of the built-in fade.
Understanding the return object structure unlocks the power to define any animation you want.
4
IntermediateAnimating multiple CSS properties
🤔Before reading on: can you animate position and opacity together in one custom transition? Commit to yes or no.
Concept: Custom transitions can animate many CSS properties at once by returning combined styles.
You can combine properties like opacity and transform in the `css` function. For example: function slideFade(node, { duration = 400 }) { return { duration, css: t => `opacity: ${t}; transform: translateX(${(1 - t) * 100}px);` }; } This moves the element from right to left while fading it in.
Result
The element slides in from the right while becoming visible.
Knowing you can animate multiple properties lets you create rich, complex effects.
5
IntermediateUsing easing and duration options
🤔Before reading on: does changing easing affect the speed curve or the total time? Commit to your answer.
Concept: Easing controls how animation speed changes over time; duration sets total animation length.
You can pass easing functions and duration to your custom transition: import { cubicOut } from 'svelte/easing'; function smoothSlide(node, { duration = 600, easing = cubicOut }) { return { duration, easing, css: t => `transform: translateX(${(1 - t) * 100}px); opacity: ${t}` }; } Easing makes the movement start fast and slow down smoothly.
Result
The element slides in with a natural speed curve over 600ms.
Understanding easing helps you make animations feel more natural and less mechanical.
6
AdvancedHandling intro and outro separately
🤔Before reading on: do you think intro and outro transitions can have different styles? Commit to yes or no.
Concept: You can define different animations for when an element appears (intro) and disappears (outro).
Svelte calls your custom transition twice: once for intro and once for outro. You can detect which phase by checking if `t` goes from 0 to 1 (intro) or 1 to 0 (outro). For example: function fadeInOut(node, { duration = 400 }) { return { duration, css: t => { if (t > 0 && t < 1) { // outro phase return `opacity: ${t}`; } else { // intro phase return `opacity: ${t}`; } } }; } You can customize styles differently for each phase.
Result
Element fades in and out with possibly different speeds or styles.
Knowing intro and outro are separate lets you tailor animations for each phase, improving polish.
7
ExpertUsing tick and custom animation frames
🤔Before reading on: can you control animation timing manually inside a custom transition? Commit to yes or no.
Concept: You can use Svelte's `tick` and JavaScript animation frames to create transitions that respond to dynamic conditions or external events.
Instead of only returning a CSS string, you can use the `tick` function to wait for the next DOM update and use `requestAnimationFrame` to control animation steps manually. This allows syncing transitions with other animations or user input. Example: function manualTransition(node, { duration = 500 }) { let start = null; return { duration, tick: (t) => { // custom logic per frame node.style.opacity = t; } }; } This approach gives full control but requires careful timing management.
Result
Animations can react dynamically and integrate with complex app logic.
Understanding manual frame control unlocks advanced, interactive animations beyond simple CSS changes.
Under the Hood
When a Svelte component adds or removes an element with a transition, it calls the custom transition function with the element node and options. The function returns an object describing how styles change over time. Svelte then runs an animation loop, updating the element's styles each frame based on progress from 0 to 1. This uses requestAnimationFrame under the hood for smooth updates. When the animation finishes, Svelte cleans up and removes the element if it's leaving.
Why designed this way?
Svelte's transition system was designed to be simple yet flexible. Returning a CSS string lets developers use any CSS property without complex APIs. Using a function with progress `t` gives full control over timing and easing. This approach avoids heavy dependencies and keeps animations declarative and performant. Alternatives like keyframe animations or imperative JS were rejected to keep code concise and reactive.
┌───────────────┐
│ Element added │
└──────┬────────┘
       │ calls custom transition function
       ▼
┌───────────────────────────────┐
│ Returns { duration, css(t) }   │
└──────────────┬────────────────┘
               │ Svelte runs animation loop
               ▼
┌───────────────────────────────┐
│ Each frame:                    │
│ - Calculate progress t (0→1)  │
│ - Call css(t) to get styles    │
│ - Apply styles to element      │
└──────────────┬────────────────┘
               │
       Animation ends, element stays or is removed
Myth Busters - 4 Common Misconceptions
Quick: Do custom transitions only work with opacity? Commit to yes or no.
Common Belief:Custom transitions are just for fading elements in and out using opacity.
Tap to reveal reality
Reality:Custom transitions can animate any CSS property, like position, scale, color, or transforms.
Why it matters:Believing this limits creativity and leads to boring animations that don't fully engage users.
Quick: Do you think custom transitions run only once per element? Commit to yes or no.
Common Belief:A custom transition runs only once when the element appears or disappears.
Tap to reveal reality
Reality:Custom transitions run separately for intro (enter) and outro (leave) phases, allowing different animations.
Why it matters:Missing this causes confusion when animations behave unexpectedly or can't be customized per phase.
Quick: Can you use JavaScript timers like setTimeout inside custom transitions safely? Commit to yes or no.
Common Belief:Using setTimeout or setInterval inside custom transitions is fine for timing animations.
Tap to reveal reality
Reality:Using requestAnimationFrame and Svelte's animation loop is necessary for smooth, synced animations; timers cause jank and desync.
Why it matters:Using timers leads to choppy animations and poor user experience.
Quick: Do you think custom transitions can only be used on elements added or removed with {#if}? Commit to yes or no.
Common Belief:Custom transitions only work with elements conditionally rendered by {#if} blocks.
Tap to reveal reality
Reality:They also work with keyed each blocks and elements added or removed by other means, as long as Svelte knows when elements enter or leave.
Why it matters:This misconception limits where you apply transitions, missing opportunities for better UI feedback.
Expert Zone
1
Custom transitions can return a `tick` function to update styles imperatively each frame, not just CSS strings, enabling complex animations.
2
You can combine multiple custom transitions by stacking them with Svelte's `transition` directive, but order and timing matter to avoid conflicts.
3
Transitions can be interrupted or cancelled if the element's state changes quickly; handling this gracefully requires careful design.
When NOT to use
Avoid custom transitions for very complex animations involving physics or multiple elements interacting; use dedicated animation libraries like GSAP or Web Animations API instead. Also, for simple fades or slides, built-in transitions are easier and more performant.
Production Patterns
In real apps, custom transitions are used for modals sliding in, list items animating on add/remove, or buttons with subtle hover effects. Developers often combine transitions with state stores to trigger animations based on user actions or data changes.
Connections
CSS Animations
Custom transitions build on the idea of animating CSS properties over time.
Understanding CSS animations helps grasp how Svelte's custom transitions generate dynamic style changes frame by frame.
Reactive Programming
Custom transitions react to state changes and lifecycle events in Svelte's reactive system.
Knowing reactive programming clarifies how transitions automatically start and stop when elements appear or disappear.
Theater Stage Lighting
Both involve controlling how things appear and disappear smoothly to an audience.
Recognizing this connection helps appreciate the artistry and timing needed to create engaging visual experiences.
Common Pitfalls
#1Forgetting to return the duration in the custom transition function.
Wrong approach:function myTransition(node) { return { css: t => `opacity: ${t}` }; }
Correct approach:function myTransition(node) { return { duration: 400, css: t => `opacity: ${t}` }; }
Root cause:Svelte needs the duration to know how long to run the animation; omitting it causes no animation or errors.
#2Using setTimeout inside the transition instead of requestAnimationFrame.
Wrong approach:function badTransition(node) { setTimeout(() => { node.style.opacity = '1'; }, 400); return { duration: 400 }; }
Correct approach:function goodTransition(node) { return { duration: 400, css: t => `opacity: ${t}` }; }
Root cause:setTimeout doesn't sync with browser repaint cycles, causing janky animations.
#3Trying to animate properties not supported by CSS or not animatable.
Wrong approach:function wrongTransition(node) { return { duration: 300, css: t => `width: ${t}` }; }
Correct approach:function rightTransition(node) { return { duration: 300, css: t => `width: ${t * 100}px` }; }
Root cause:CSS properties need valid units and must be animatable; missing units or invalid properties cause no effect.
Key Takeaways
Custom transitions in Svelte let you define exactly how elements animate when they appear or disappear by returning style changes over time.
They work by returning an object with duration and a css function that receives progress from 0 to 1, allowing any CSS property to animate.
You can customize intro and outro animations separately and control easing and duration for natural effects.
Understanding the animation loop and how Svelte applies styles each frame helps you create smooth, performant animations.
Avoid common mistakes like missing duration or using timers; use Svelte's animation system for best results.