I want to realize a simple page (route) transition in Sapper. Something that is easily achievable with Nuxt for example. Does anyone have an idea how to realize that with Sapper?
I already wrapped my page content into a div with a transition:fade directive. This works. Yet, the two pages transition at the same time, meaning while one page transitions out the other one already transitions in. It would be great if someone pointed me in the right direction. Thanks!
Let me just start of by saying I don't know if this is the most effective way to do it. This is the way I solved it and it works great for me.
I first made my own custom variation of the 'fade' transition and put it in 'components/pageFade.js'
import { sineOut } from "svelte/easing";
let duration = 250;
let delay = duration;
let delayZero = 0;
export const fadeIn = _ => ({
duration,
delay,
easing: sineOut,
css: t => `opacity: ${t}`
});
export const fadeOut = _ => ({
duration,
delay: delayZero,
easing: sineOut,
css: t => `opacity: ${t}`
});
Then for all files I wanted to have this transition on I did the following:
<script>
import { fadeIn, fadeOut } from "../components/pageFade";
// All your other JS goes here
</script>
<style>
/* Styles go here */
</style>
<main in:fadeIn out:fadeOut>
<!-- All the normal HTML goes here -->
</main>
I would then use that as a template on almost every single one of the pages, which seems like a lot but it's not too bad.
Hope it helps and let me know if you have any other questions!
Max
If you want to include transition in _layout.svelte and don't need to include them in every route here is an alternative.
Here is a simple fly in/out from top transition.
<!-- src/component/PageTransitions.svelte -->
<script>
import { fly } from 'svelte/transition';
export let refresh = '';
</script>
{#key refresh}
<div
in:fly="{{ y: -50, duration: 250, delay: 300 }}"
out:fly="{{ y: -50, duration: 250 }}"
>
<slot/>
</div>
{/key}
And here is the Sapper layout component
<!-- src/routes/_layout.svelte for Sapper -->
<script>
import { page } from '$app/stores'; // svelte@next
import Nav from '../components/Nav';
import PageTransitions from '../components/PageTransitions';
export let segment;
</script>
<Nav {segment}/>
<PageTransitions refresh={segment}>
<slot/>
</PageTransitions>
And here is the SvelteKit (svelte@next) layout component
<!-- src/routes/$layout.svelte for Svelte@next -->
<script>
import { page } from '$app/stores'; // svelte@next
import Nav from '../components/Nav';
import PageTransitions from '../components/PageTransitions';
</script>
<Nav segment={$page.path}/>
<PageTransitions refresh={$page.path}>
<slot/>
</PageTransitions>
And for completeness here is a simple Nav component
<!-- src/component/Nav.svelte -->
<script>
export let segment;
</script>
<style>
a {
text-decoration: none;
}
.current {
text-decoration: underline;
}
</style>
<div>
<a href="/" class='{segment === undefined ? "current" : ""}'>Home</a>
<a href="/about" class='{segment === "about" ? "current" : ""}'>About</a>
</div>
NOTES:
We make the component reactive by creating a refresh
prop and using key
directive which means that when the key changes, svelte removes the component and adds a new one, therefore triggering the transition.
In the layout component we pass the segment (route) as refresh
prop and therefore the refresh key changes as the route changes.
Here is a demo of the sample code above and the github repo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With