Simple Animated Page Transition in Svelte

- 2 minutes read

Adding a page transition can make navigation on some apps look smoother and feel more fluid.

In this example, we’ll build a simple and customizable page transition for a SvelteKit app.

Let’s begin by creating a new Transition.svelte component:

<!-- Transition.svelte -->
<script>
    import { onMount } from 'svelte';
    import { fly } from 'svelte/transition';
    export let refresh = ``;
</script>

{#key refresh}
    <!-- You can modify the in:fly and out:fly attributes to your liking! -->
    <div in:fly={{ delay: 100, duration: 200, y: -10, }} out:fly={{ duration: 100,  y: 10, }}>
        <slot />
    </div>
{/key}

Then, in our __layout.svelte file, we can place the content we want to animate within our Transition.svelte component.

The following example assumes that Transition.svelte is placed in $lib/components/Transition.svelte.

This example also animates everything below the navbar, but you can position the <Transition> component however you want:

<!-- __layout.svelte -->
<script context="module">
    export const load = async ({ page }) => ({
        props: {
            key: page.path,
        },
    });
</script>

<script>
    import Transition from '$lib/components/Transition.svelte';
    export let key;
</script>

<nav>
    <p>This content will not be animated!</P>
</nav>
<Transition>
    <!-- Everything inside this transition component will be animated! -->
    <!-- In this example, that encompasses all the page contents besides the navbar. -->
    <slot />
</Transition>

If you’ve reset your layout in certain parts of your app using the __layout.reset.svelte file, then you might want to check whether you want to animate pages that descend from that layout reset as well.

Link to this section Page transition accessibility considerations

The following Transition.svelte variant disables the page transition for users that explicitly prefer reduced motion in their browser settings:

<!-- Transition.svelte -->
<script>
    import { onMount } from 'svelte';
    import { fly } from 'svelte/transition';
    export let refresh = ``;

    let animations = false;

    onMount(() => animations = window.matchMedia(`(prefers-reduced-motion: reduce)`) === true || window.matchMedia(`(prefers-reduced-motion: reduce)`).matches !== true);
</script>

{#key refresh}
    {#if !!animations}
        <!-- You can modify the in:fly and out:fly attributes to your liking! -->
        <div in:fly={{ delay: 100, duration: 200, y: -10, }} out:fly={{ duration: 100,  y: 10, }}>
            <slot />
        </div>
    {:else}
        <slot />
    {/if}
{/key}

To improve your app’s accessibility, I strongly suggest opting for this modified Transition.svelte.

Link to this section Conclusion

I hope you enjoyed this quick little tutorial on how to add page transitions to your SvelteKit app, but I also hope that you implemented the reduced motion check!

I lastly want to note that Svelte offers many other transitions besides fly that you can tinker with.

Anyway, thanks for reading.