DEV Community

loading...

Simple Page Transitions with SvelteKit

Evan Winter
Front-end engineer in Chicago.
・2 min read

Demo: https://sveltekit-page-transitions.netlify.app/
Source code: https://github.com/evanwinter/sveltekit-page-transitions

Overview

  1. Create a <PageTransition /> component which transitions out and back in when page navigation occurs.

  2. Wrap your layout file's <slot /> (the current route's content) in the <PageTransition /> component.

Step 1: Creating the <PageTransition /> component

Create a component file at src/lib/components/PageTransition.svelte.

<!-- PageTransition.svelte -->
<script>
  import { fly } from "svelte/transition"
  export let refresh = ""
</script>

{#key refresh}
  <div in:fly={{  x:-5, duration: 500, delay: 500 }}
       out:fly={{ x: 5, duration: 500             }}>
    <slot />
  </div>
{/key}
Enter fullscreen mode Exit fullscreen mode

When the value of refresh changes, the component will destroy and recreate itself, executing the in:fly and out:fly transitions at those steps.

As far as the user is concerned, these things happen almost simultaneously –– so we need a delay on the in transition so that it starts after the old route has transitioned out.

Step 2: Using the <PageTransition /> component

Create a layout file at src/routes/__layout.svelte.

<!-- __layout.svelte -->
<script>
  import PageTransition from "$lib/components/PageTransition.svelte"
  export let key
</script>

<!-- 1. Assign current route's path to `key` prop -->
<script context="module">
  export const load = async ({ page }) => ({
    props: {
      key: page.path,
    },
  })
</script>

<div>
  <nav>
    <a href="/">Home</a>
    <a href="/about">About</a>
  </nav>

  <!-- 2. Pass `key` prop to the component so it knows when to transition -->
  <PageTransition refresh={key}>
    <slot />
  </PageTransition>
</div>
Enter fullscreen mode Exit fullscreen mode

On page load, we get the page's path with the load function. So when the page changes, we get a new key prop returned by the load function.

That key prop is passed to the PageTransition component, so when a change is detected (e.g. page navigation occurred), the component does the out and in transitions.

Discussion (2)

Collapse
tonborzenko profile image
Anton Borzenko • Edited

Thank you for great job. Is it possible to use import { page } from '$app/stores', how do you think? I tried to use $page.path as a key, but it has a bug in animation between components...

Collapse
evanwinter profile image
Evan Winter Author • Edited

What kind of bug? Is it changing to the next route before it finishes the "out" transition of the previous route?

If so... and I'm not sure I'll word this right... but essentially, I think the issue is that the $page.path variable is reactive and updates immediately when you navigate to the next route, irrespective of which render instance of the component it started with. With the approach shown in the post, we store a reference to the previous route that's scoped to the particular render instance, so PageTransition.svelte doesn't see a new key until after the first route has transitioned out (destroyed itself) – then, prior to transitioning back in (recreating itself), it loads the new key for the new route.