Fluid page transitions with Svelte & Sapper
Tags: svelte, ui
Published: 2019-07-03 07:29:41

---
title: Fluid page transitions with Svelte & Sapper
published: true
description: Look mom, no client-side library or runtime!
tags: Svelte, UI
---

UPDATE: This post is now over 2 years old, but it's still kinda relevant. This technique should work exactly the same with [SvelteKit](https://kit.svelte.dev).

Ever come across websites with cool animations whenever navigating from one page to another? For example [this website](https://page-transitions.com/) by [Sarah Drasner](https://twitter.com/sarah_edo). Usually, you'd use client-side libraries and clever CSS tricks to achieve these sort of things. Probably nothing wrong with that, but it adds to your website's overall download size, and your CSS will become hard to maintain as your site grows in complexity. However, thanks to [Svelte](https://svelte.dev), we can now do these cool things without any client-side library or CSS trickery:

![GREAT SUCCESS](https://thepracticaldev.s3.amazonaws.com/i/82y5qvdmiqh8t3ntor0g.gif)
([Try it out](https://codesandbox.io/embed/fluidui-9l3t2))

So now we can have cool PWAs, that are server-side rendered, have smooth page transitions, and are compiled down to really tiny amounts of javascript. With no need for client-side libraries,  virtual DOMs, or shuffling CSS classes around. Oouwee!

_And with that, our lives are now complete. Because what else could we possibly want? We should now all go and praise [Rich Harris the JavaScript God](https://twitter.com/rich_harris). Or do we need more JavaScript frameworks? Don't we have enough? I can't take it anymore. Make it stop. Aaaaaahhh this is the end._

## How?

These animations all use Svelte's [crossfade transition](https://svelte.dev/tutorial/deferred-transitions). If you haven't used it before, I suggest checking out [the tutorial](https://svelte.dev/tutorial/deferred-transitions). It will teach you how to crossfade two elements within the same component. But we are interested in crossfading an element from **one component into another** (in Sapper, each page is a component). The trick to making the crossfade transition work across different pages (or components) defined in separate files, is to create the crossfade transition in its own module/file, and `import` it into the different components. Check it out:

Here we create the crossfade transition in its own file and export the `send` and `receive` functions so that we can reuse them in different files.
```js
// crossfade.js
import { quintOut } from 'svelte/easing';
import { crossfade } from 'svelte/transition';
const [send, receive] = crossfade({
    duration: d => Math.sqrt(d * 300),
    fallback(node, params) {
        const style = getComputedStyle(node);
        const transform = style.transform === 'none' ? '' : style.transform;

        return {
            duration: 600,
            easing: quintOut,
            css: t => `
                transform: ${transform} scale(${t});
                opacity: ${t}
            `
        };
    }
});

export {send, receive};
```

And then we use the `send` and `receive` function.

```html
// page1.svelte
<script>
  import {send, receive} from './crossfade.js';
</script>

<main>
  <h1 out:send="{{key: 'h1'}}" in:receive="{{key: 'h1'}}">Look, I'm above the image</h1>
  <img out:send="{{key: 'borat'}}" in:receive="{{key: 'borat'}}" alt='Borat' src='great-success.png'>
</main>

```

And then use the **same** `send` and `receive` function again, making the crossfade work across components.
```html
// page2.svelte
<script>
  import {send, receive} from './crossfade.js';
</script>

<main>
  <img out:send="{{key: 'borat'}}" in:receive="{{key: 'borat'}}" alt='Borat' src='great-success.png'>
  <h1 out:send="{{key: 'h1'}}" in:receive="{{key: 'h1'}}">Now I am below the image</h1>
</main>

```

The container needs to be absolutely positioned, otherwise it won't work.

```css
// global.css
main {
  position: absolute;
  width: 100%;
}
```

There you go. Thanks for reading. 

Visit https://buhrmi.dev if you'd like professional support.