Simplified `view-transition-api` for Sveltekit.
npm install sveltekit-view-transitionSimplified view-transition-api for Sveltekit.

!GitHub last commit
!npm
!npm
Svelte has kinda spoiled us: we have built in animations and transitions so that we can add a little bit of micro-interactions to our websites and apps. Do you need to animate a list reordering? flip comes to the rescue. Is a div moving and morphing from one list to another? crossfade is your friend. The web platform must have seen how much svelte developers love those kind of things and has provided us with a brand new, fully progressive enhance-able api: the view transition API. This api not only allows you to animate between two states of your application regardless of the fact that two elements are actually the same or not (something that before was only possible with third party libraries or very complex code) but allows you to animate elements that are on different pages!
SvelteKit provides a way to hook into the navigation to allow the developer to start a view transition before the navigation and they do so with a very low level primitive. Here's how you can enable view transitions in SvelteKit
``ts`
onNavigate((navigation) => {
if (!document.startViewTransition) return;
return new Promise((resolve) => {
document.startViewTransition(async () => {
resolve();
await navigation.complete;
});
});
});
While not very complex, writing this snippets everywhere you need it can get quite tedious and sometimes based on how the view-transition-api works you might need to do other things like add classes or change the style of an element.
sveltekit-view-transition aim to ease the experience of writing easy and complex transitions in SvelteKit!
Before going in the details of how this library works and how to make use of it i want to leave here a wonderful article that explains what they are and how to use them in Vanilla JS from Jake Archibald, the main mind behind them.
> Warning
> While view transitions are cool please don't overuse them as having too much motion can worsten your users experience rather than enhance it. Also PLEASE respect your users preference for reduced motion with @media (prefers-reduced-motion)
`bash`
npm i -D sveltekit-view-transition@latest # or pnpm/yarn
_src/routes/+layout.svelte_
`svelte
`
This will automatically enable the default transition to every navigation.
Optionally, the default animation can be modified via ::view-transition-old(root) and ::view-transition-new(root) like so:
_src/routes/+layout.svelte_
`svelte
`
It's often useful to give specific parts of the page their own unique view transitions. We can do this by setting an element's view-transition-name.
One way to do this is with transition, a svelte action returned by setupViewTransition.
transition accepts a string representing the view-transition-name that should be assigned to the element using it:
`svelte
`
As you can see, the header's view transition can now be modified via ::view-transition-old(header) and ::view-transition-new(header).
If you want to be a bit more creative with the transitions, you can pass an object to the transition action instead of a string. This object accepts the following options:
- name: the view-transition-name _(required)_classes
- : classnames to apply to the target element during the transition. An array of strings or a function that returns one.applyImmediately
- : Whether the transition should be applied immediately, or only during the actual navigation. A boolean or a function that returns one.shouldApply
- : Whether the transition should be applied or not. Can be a boolean or a function that returns one.
Let's take a look at each of these options in more detail:
The view-transition-name -- the only required parameter. It can be a string _or_ a function that takes a navigation object and returns a string, and will be applied to the target element during the transition. This is equivalent to setting the style property view-transition-name on an element.
Apart from the navigation object this function also receive the HTMLElement of the action (it's the property node inside the prop object) and a boolean that express if this element is actually in the viewport at the time of the transition (it's the property isInViewport inside the prop object). This allow you to easily skip a transition if the element is not in the viewport to avoid having elements that fly off the viewport (inspired by this tweet by Ryan Florence)
Either an array of strings, or a function that returns an array of strings. These classes will be applied as classnames to the root element during the transition.
To demonstrate this, let's assume we want to apply a unique transition to our header anytime our "back" button is clicked.
This can be achieved by returning an array, i.e. ["back"], to our classes callback.
Apart from the navigation object this function also receive the HTMLElement of the action (it's the property node inside the prop object) and a boolean that express if this element is actually in the viewport at the time of the transition (it's the property isInViewport inside the prop object). This allow you to easily skip a transition if the element is not in the viewport to avoid having elements that fly off the viewport (inspired by this tweet by Ryan Florence)
`svelte
name: 'header',
classes({ navigation }) {
if (navigation.to?.route?.id === '/') {
return ['back'];
}
},
}}
>
Back
`
Now, we can target .back::view-transition-old(back) and .back::view-transition-new(back) in our CSS and those transitions will only be applied when navigating to the home page /.
In the example above, you can see we're destructuring navigation from the provided OnNavigate object _(the same object that sveltekit will pass to the onNavigate function)_. This object contains a lot of useful information, including the page you are navigating to, allowing us to apply classes conditionally based on the navigation.
Click here to see the full
Navigation interface.
`ts/blog/[slug]
interface Navigation {
/**
* Where navigation was triggered from
*/
from: {
/**
* Parameters of the target page - e.g. for a route like , a { slug: string } object.null
* Is if the target is not part of the SvelteKit app (could not be resolved to a route)./blog/[slug]
*/
params: Record
/**
* Info about the target route
*/
route: { id: string | null };
/**
* The URL that is navigated to
*/
url: URL;
} | null;
/**
* Where navigation is going to/has gone to
*/
to: {
/**
* Parameters of the target page - e.g. for a route like , a { slug: string } object.null
* Is if the target is not part of the SvelteKit app (could not be resolved to a route).form
*/
params: Record
/**
* Info about the target route
*/
route: { id: string | null };
/**
* The URL that is navigated to
*/
url: URL;
} | null;
/**
* The type of navigation:
* - : The user submitted a