You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are lots of issues on Github already and countless discord threads about page transitions in sveltekit, but none of them get to an all around satisfying solution.
I'm writing yet another issue about this topic because I think there should be some discussion about a higher level solution instead of the currently available hacky solutions.
I will now present two currently available/used solutions to page transitions:
Basic approach
A cumbersome but perfectly working solution is to put a div wrapper with in and out transitions into each +page.svelte and have a +layout.svelte with some css to overlay the two transition wrappers of the pages over another like this:
The .transition-element wrapper needs to be added to all +page.svelte files, so lots of duplicated code.
It is not possible to transition components that would normally live in +layout.svelte together with the +page.svelte in the same .transition-element wrapper. For example it would make sense to transition the footer in and out together with the +page.svelte so it doesn't visually jump to its new position. Of course you can also put the footer into the +page.svelte but that creates even more duplicated code.
{#key} block approach
Both the issues from the basic approach can be resolved by moving the duplicated code from +page.svelte to +layout.svelte and use the {#key} block that is used in most of the discussions around page transitions. The {#key} block is used to unmount and remount the .transition-element wrapper from the example above in the layout instead of the page, in this example this is triggered by the change of $page.url.pathname store:
The main issue with this approach is that the unmounting/remounting of the elements inside the {#key} block is not tightly coupled with the the mounting of the +page.svelte component, instead it is purely dependent on the timing when the variable inside the {#key} block changes.
In the example code the $page.url.pathname store is used to trigger the remounting, but unfortunately this store changes to late so when navigating to a new route the new +page.svelte component is added before the {#key} block triggers so sometimes you can see a short flash of the new page before it is hidden again to reappear with the transition. Since this is a millisecond timing issue not everyone will experience this.
To prevent the timing mismatch we could look for a variable that has a better timing to use in the {#key} block. There are a few candidates that emerged in discussions about this specific timing issue:
navigating from $app/stores
timing is to early
onNavigate from $app/navigation
timing to early
load() function in +layout.js using url.pathname as changing variable as a data property sveltelab demo
this is s far the most consistent candidate to use as a timer, but you need to create a +layout.js only to get this and it really feels horrible to use the load() function for this stuff.
conclusion
IMHO the usage of the {#key} block for this is fundamentally flawed because it is highly timing dependent and not coupled to svelte updating the <slot /> at all.
Describe the proposed solution
I would like to discuss possible first party solutions in svelte or kit that enables users to easily wrap stuff around the slot that is always unmounted/remounted when the slot has changes.
off the top of my head I could imagine two possible syntaxes for this:
In this example <slotWrapper> is a svelte internal component like <slot /> that always mounts together with the +page.svelte component inside <slot />.
This discussion was converted from issue #11102 on November 22, 2023 11:45.
Heading
Bold
Italic
Quote
Code
Link
Numbered list
Unordered list
Task list
Attach files
Mention
Reference
Menu
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
-
Describe the problem
preface
There are lots of issues on Github already and countless discord threads about page transitions in sveltekit, but none of them get to an all around satisfying solution.
I'm writing yet another issue about this topic because I think there should be some discussion about a higher level solution instead of the currently available hacky solutions.
I will now present two currently available/used solutions to page transitions:
Basic approach
A cumbersome but perfectly working solution is to put a div wrapper with
in
andout
transitions into each+page.svelte
and have a+layout.svelte
with some css to overlay the two transition wrappers of the pages over another like this:+page.svelte
+layout.svelte
Demo: sveltelab
issues with this approach
.transition-element
wrapper needs to be added to all+page.svelte
files, so lots of duplicated code.+layout.svelte
together with the+page.svelte
in the same.transition-element
wrapper. For example it would make sense to transition the footer in and out together with the+page.svelte
so it doesn't visually jump to its new position. Of course you can also put the footer into the+page.svelte
but that creates even more duplicated code.{#key} block approach
Both the issues from the basic approach can be resolved by moving the duplicated code from
+page.svelte
to+layout.svelte
and use the{#key}
block that is used in most of the discussions around page transitions. The{#key}
block is used to unmount and remount the.transition-element
wrapper from the example above in the layout instead of the page, in this example this is triggered by the change of$page.url.pathname
store:+layout.svelte
+page.svelte
Demo: sveltelab
issue with this approach
The main issue with this approach is that the unmounting/remounting of the elements inside the
{#key}
block is not tightly coupled with the the mounting of the+page.svelte
component, instead it is purely dependent on the timing when the variable inside the{#key}
block changes.In the example code the
$page.url.pathname
store is used to trigger the remounting, but unfortunately this store changes to late so when navigating to a new route the new+page.svelte
component is added before the{#key}
block triggers so sometimes you can see a short flash of the new page before it is hidden again to reappear with the transition. Since this is a millisecond timing issue not everyone will experience this.To prevent the timing mismatch we could look for a variable that has a better timing to use in the
{#key}
block. There are a few candidates that emerged in discussions about this specific timing issue:navigating
from$app/stores
timing is to early
onNavigate
from$app/navigation
timing to early
load()
function in+layout.js
usingurl.pathname
as changing variable as a data property sveltelab demothis is s far the most consistent candidate to use as a timer, but you need to create a
+layout.js
only to get this and it really feels horrible to use theload()
function for this stuff.conclusion
IMHO the usage of the
{#key}
block for this is fundamentally flawed because it is highly timing dependent and not coupled to svelte updating the<slot />
at all.Describe the proposed solution
I would like to discuss possible first party solutions in svelte or kit that enables users to easily wrap stuff around the slot that is always unmounted/remounted when the slot has changes.
off the top of my head I could imagine two possible syntaxes for this:
style 1
+layout.svelte
In this example
<slotWrapper>
is a svelte internal component like<slot />
that always mounts together with the+page.svelte
component inside<slot />
.style 2
+layout.svelte
TransitionWrapper.svelte
In this approach the slot gets a wrapper component prop that must have a slot.
Maybe there are other use cases for something like this as well?
I really would love to get some thoughts from others about this!
Importance
would make my life easier
related issues
#5938
#7877
Beta Was this translation helpful? Give feedback.
All reactions