Introduction and project setup
Hey friends. Today I'm going to show you some awesome page transitions using SvelteKit. So here I'm just using the regular Svelte demo project so we can emulate a real project and don't have to set anything up. So just create a new Svelte project if you want to follow along and select the demo option. As you can see, this is alright but it's kind of vanilla, right? So how can we spice this up? First thing we're going to do is open the layouts. I'm going to press Ctrl+P inside the project, then I'm going to start typing layout. Let's open the root layout. So basically what you're going to do here: we have to use this layout and here is a slot where every page goes, right? So you can say hello; this is going to show for every page. And basically in SvelteKit, if you didn't know, every page is basically a component. So if we can animate components mounting and unmounting, we can do the same thing for pages. But how can we do this? Right, we have to first know when the navigation happened and then we have to somehow mount and unmount this. So how do we do this? Well, we're going to learn a couple of neat tricks, but first let's see how we can see when the page changed.
Using the page store to detect navigation
So we can use the page store. I can say import page from $app/stores. I'm going to be $app and it's going to be stores, I think. So let's just do it like this, and then I'm going to use the snippet pre just so we can see what is inside. And we have to preface it with the dollar because this is a Svelte store. So this is just syntactic sugar so you can subscribe to it. And now we get something interesting: we get all the information about this page. So we can see route ID. And now when we navigate you can see the ID changes to about, then it's swirls and etc. Even we have some other options like the URL. So for example it won't show here — let me just do a console.log so I can say page.url and we can get even more options. If I just open the developer tools Ctrl+Shift I, let me just save this, and now we can see for the URL we have host, hostname, ref, origin, and we're interested in pathname, right? When we change this and if the console.log updates we can do this. This is going to update and now we're also going to see that the pathname updates.
Key blocks to mount and unmount pages
But how can we create and recreate these blocks? Thankfully in Svelte you can use a key block like this. So you can say key and then you can give it the value. When this value changes, whatever is inside of here is going to get destroyed or unmounted and then it's going to mount it back again. So that's how we can mount and unmount pages in this case. And what we're going to use for the value we're going to use, of course, page and then you can use route ID, or we can say pathname like this. And now I'm going to show you what the problem is with this approach. So right now there's nothing going on but we need to add our transitions. How do we add a transition? We can just add an element and now we can use a transition from Svelte. We can say transition; we're going to import fly. So I just pressed enter and this is imported at the top. Sometimes the import here is weird so keep attention if you're doing an auto import. Looks fine right now. And then we can just say let's just say that x is going to be -200 and let's just save this. And now since we're going to update this each time the key block is going to get destroyed and created again, so let's see how this works.
Problem with in/out overlapping and layout solution
Awesome. But can you notice a problem? Pay attention how at home — and let's just make it more obvious — we can say duration two seconds. So what's going to happen? This happens too late. Right? Our component is already going to be mounted. So what's going to happen is the about page is going to go through the out transition and then in transition again. So let's see what happens. You can see it transition out and then it transitions again. Ah, that sucks. So what do we do now? Well basically this is why this method doesn't work for using the page store. What we have to do is know that the page changed in advance and we can do that using a layout page. So we can just send it as a prop again the same pathname and then this is going to work fine. Alright, so how do you do that then? I'm going to go to the project source routes and now we can create a +layout.ts or +layout.server; which one you pick, does it matter? So you can just say +layout.ts and I'm going to export the load function: export function load and now we can destructure the URL which is the same thing as you saw from the store. So then we can return a URL which is going to be the URL and what we want from the URL: pathname. Right, same thing we used before. So right here we can go and we can delete this. Let's just remove all this code, we don't need this anymore. So now we're just going to take the prop: export let data. And now we can change this to be data.url. Alright, so let's save this and let's see.
Fixing overlap with delays and directional exits
This already looks a lot better. But as you can see here is a problem because in Svelte the transition is going to play in and out both; you can see they overlap. Alright, so how can we solve this problem? And basically you can solve this easily. You can just say in, for example fly, and now the duration since it's two seconds give it a delay which is going to be also two seconds. And now we can also specify an out duration again two seconds. We can save. Of course I put the wrong in — we don't want the curly braces — we can just do it like this and then let's remove this and also let's add equals, right? So we can just save this and now you're going to see there's going to be a delay for the intro animation. So if you go to about, you can see, ah beautiful. So now it works. Of course this is really slow so let's put it to something 300 milliseconds. And that's really awesome. So you can see if we go to the about, the about is going to show and we can also make it so for example if we enter right here it's going to go from the left when we enter. But let's say we want to exit on the right we can say here x 200, let's say this. And now this should go to the right and we should get home from the left. And how awesome is this? As you can see here is some jank also on the page, so there's probably styles in here in the body. Let's see. So for right now you can set something like overflow: hidden. Save it and then you won't get this jank anymore. Alright that's awesome.
Custom transition functions: scale example
But I also want to show you how you can spice this up and create your own custom transitions. So let me just close this; we don't need layout anymore. So basically custom transition functions are basically like Svelte actions but they return a special transition object, so you can create whatever transition you want. So let's create a transition where for example this element when it enters is going to scale from the left and when it exits it's going to scale back to the right. So how do we create a custom transition in Svelte? Basically we can just go here and now we can say function, let's name it scale. And now this is going to take in a couple of things: it's going to take a node which is going to be the element itself — so that's the reference to the element — and now it's going to take some options or parameters. We can destructure them; we can just say delay, duration, and easing. And we can export a default easing from Svelte, so it has a lot of easings you can pick from. Let's pick something like cubicIn and this is going to come from import { cubicIn } from 'svelte/easing' I think. Yeah easings. So we can find like here and we can set delay to be zero, duration default 300 milliseconds, and then we can set it to a default empty object. And we're going to look at the types a bit later. Let me just say language typescript. Awesome. And also another parameter that you're always going to have is a direction which Svelte is going to do for you but we can just destructure it from options. We can give it a default 'both' because the value is in, out, or both and we can also set it to a default object. Alright, so let me show you how simple this is. Basically the only thing you have to return from this is a special object that has the delay, it has the duration, easing, and now as well to use a CSS. So this isn't even JavaScript, so it's very performant; Svelte is going to create a CSS animation from this and you only have to pass it a CSS function which is going to take t which means time — it goes from 0 to 1. It's really, it's not the duration of your transition but it's just going to track when it starts and when it's done. And basically this magical number t 0 to 1 you can also apply easings to it which is just some fancy math and that's how you get also easings etc. So the rest here is just regular CSS. Right, so this is beautiful. So we can just say we can use the new CSS property scale so we don't even have to use transform and then you can use template literal. So this is going to go from 1 to 0, that's it. And then we can spice it up by using transform-origin so you can say center center which is the default. Let me save this and let's use this transition. So you can go here we can say scale. Now we don't need X anymore and we can keep the rest because if you didn't know that's how all of these transitions in Svelte also work: they basically implemented like this even in the source code which is really awesome how simple it is considering you might be thinking how Svelte is this complicated thing but even the source code for this auto transitions is relatively simple and easy to understand.
Easing, direction mapping, and playful effects
Alright, so now basically we didn't do anything special here but now when we transition you should see it should just scale. But this is really not what we want. Even though it's a cool effect you can also do cool things like — let me just remember — elasticOut. Let's see elasticOut. So this is going to be springy going. You can see like this, you can have a lot of fun and give personality to your site. But yeah, let me just switch it back to what we used in cubic and you can also — let me just — looks well easings. I think there's a visualizer with all of the easing function visualization so I'm going to link that in the description. Give it a second just so it loads. Oh this is a cool one I didn't know about this but I was like thinking about another one: is visualizer I think that was it, yeah from the official Svelte site. Give it a second. Yeah, so you can see here you can pick whatever you want: easing-out, let's see ease-sine, cubic. As you can see these are all just math functions that apply to that zero-to-one scale. So that's how you get this easing which is really cool. So I'm going to link that and of course everything is going to be linked in the post. Alright, but what is a cool thing that we can do here? So how can we transform-origin say okay go from the left and then go from the right? Basically we can use this direction here, so we can map the origin. We can do something like this. We can say const origin and now we can just give it value. So we can say okay when you're 'in' it's going to be center left; when you're 'out' it's going to be center right or actually let's just say bottom not center, and then the default which is going to be both is going to be center center. Alright, so how do we use this? Well simple, let's go here, use a template and now you can say origin and let's pass the direction. How awesome is this? Okay, so now we can do this and now let's see. Oh but of course I'm silly and as you can see one character down. You really have to pay attention what you're typing here so this is transform-origin. And if we go here we can see oh it goes to the right, it starts from the left. How cool is this friends? Right? Ah you can have so much fun. Awesome. Alright but let's spice it up: we're going to show you something a bit more awesome. So trend it off — let's create a fun effect. Instead of scale I'm going to right click, I'm going to rename. Let's name it flash and then I can remove origin since I'm going to use this and we can also use rotate and we can use the turn value in CSS. So we can say t-turn. So this is going to go from 1 to 0 which is going to be 360 degrees, right? So let me just save this and now I'm going to say that this should be one second here. Let me do it like this and then if you can see now we're going to get this effect. And I also prepared a curious sound effect so we can also do this. We can say direction: if it's going to be out then I'm going to play flash. And now when we go to home to about... how beautiful is this friends.
Abstracting transitions into a reusable component and typing
Another way how we can play this sound — since we have already discussed transition — we don't have to use it but there's also on:intro, transition:start, you can also play the sounds or do whatever you want here. As again you can read this more in the Svelte documentation. But how awesome is this? So now we have custom transitions as well; you can impress your friends and co-workers. The only thing left is you can abstract this into a Svelte component. So let's do that. I'm going to go to the sidebar routes and you can create this inside lib wherever you want. I'm just going to create it here so we can say transition.svelte. Let me just close this. I'm going to copy this part over. So we're going to do it like this. Let's say the script and now we just need the key. So we can just use the key here and then we can also export let duration and we can have 300 by default. Actually I can do it like this. So now we can go to the duration we can leave it like this. The delay should be the amount of the duration if you want to avoid that mistake, right? But of course depends what you're doing here. Let me save this. And now let's also take flash so we can go here which you can also store in a separate file if you want. I'm going to store it here for fun. Let's see what else are we missing. You can also take this, pour the sound from here. We're also going to need cubic and fly but you're not using fly right so you can just go here let's remove Fly. Let's save it like this so we can remove all of this code. We can remove this and now we can go here we don't need this block anymore so this is just going to be slot like before. And now we can just import let's see if it's going to autocomplete transition. Awesome. So we have lib/transition from svelte and we can just leave it here. You can name this whatever you want. I like to be descriptive and say pageTransition. So we can go here and name it page-transition. Let's wrap it like this and now it's going to want — let's see the duration and the key — and the key of course is going to be data.url and what else did we say duration? Yeah. So we can give it a duration of one second so we write everything and now let's see this should work. How beautiful is this friends. Chef's kiss. Alright so that's it friends. Let me just show you the types for this if you're curious about this. If you don't care about TypeScript you can leave right now but let's also just give this a string so this really isn't that bad to type. We just need a type of Params and Options. So you can say type Params; you can also be more specific you can say flashParams so delay is going to be optional, it's a number. Then you have a duration which is again optional and now you can find this by just browsing through the Svelte code. So Svelte exposes this easing function you can import so you can see from 'svelte/transition' that's basically it with Params. So we can do it like this. Save and now this should work great. And we can also give it a return which is going to be another type that is going to be transition config. So we don't really have to type this function; now it knows about T and also if you didn't know you can return U which is the opposite of T. So T goes from 0 to 1 and U goes from 1 to 0 so it's basically opposite of that. Now we have the Params and now we just need to type the Options so these directions I couldn't find the exported type for that so you can just do OptionsDirection which is again going to be optional so there's 'in', 'out', and you have 'both'. And yeah you can also use this if you have an options object here so you can just say options and save this and that's basically it. So now we have this new function we can reuse; our beautiful transition is working as expected. All right friends, so don't forget to like and subscribe. You can find my Patreon in description and don't forget to join the Discord. And as always, thank you for watching and catch you in the next one. Peace. foreign