Sapper: Element transitions between pages

Created on 30 Jun 2019  路  9Comments  路  Source: sveltejs/sapper

Here is an interesting site demonstrating element transitions when navigating between pages. I thought it would be cool if sapper could do something like this natively with the animate directive. So, for example:

index.html:

<div class="something">
  <div id="amazing" animate:flip={{duration: 200, key: 'hello'}}>I'm here</div>
</div>
<style>
#id {
  width: 100px;
  height: 100px;
}
</style>

detail.html:

<div id="amazing" animate:flip={{duration: 200, key: 'hello'}}>Now I'm over here</div>
<style>
#id {
  display: absolute;
  top: 30px;
  width: 200px;
  height: 200px;
}
</style>

And between navigation, sapper would find the element with the same ID or key, and automatically apply a flip animation.

Most helpful comment

Okay, I figured it out how to do this without modifying the Svelte source code except for a tiny tweak: https://github.com/sveltejs/svelte/pull/3175

updated my blog post, too: https://dev.to/buhrmi/svelte-component-transitions-5ie

All 9 comments

To make it work, I guess the sapper router would check if there are any keyed elements inside the current page (and layout) component, see if there are any matching keyed elements on the new page (or layout) component, and then create a FLIP transition between them.

Looks like @Rich-Harris already thought of that as "Scenario 3" in this issue https://github.com/sveltejs/svelte/issues/1431 ... But this hasn't been implemented, right?

Been working on this a bit. At first I tried to use the built-in crossfade() function, but the problem is that the old page component stays in the page until the animation is completed and the new page component is being appended beneath it.
pageflip

So I started to work on a new custom animation, that functions similar to crossfade(), but with the duration of the out-animation set to 0. The way I wanted it to work is:

  1. Out-transition is called. The duration is 0, so all it does is store the clientRect of the "sending" element.
  2. The old page component is removed from the DOM and the new component is rendered
  3. The In-transition is called, calculating the position delta and play the FLIP animation.

However, the problem that I can't get around, is that sapper does not remove the old page component before calling the In-transition function. That means that the clientrect.top that is used to calculate the FLIP animation is not correct. Now I wonder if there is a way to modify sapper to not call the in-transition before removing the old page component (if it doesn't have an animation with a duration > 0).

Progress 馃槃 Have to change Svelte internals a little bit to get it working. Still some bugs but I'll figure it out and make a PR

ezgif-1-3b42140b2353

Getting there
rkO24Wit7J

Okay, I figured it out how to do this without modifying the Svelte source code except for a tiny tweak: https://github.com/sveltejs/svelte/pull/3175

updated my blog post, too: https://dev.to/buhrmi/svelte-component-transitions-5ie

hmmmm...sorry if my question is simple but how can I do a simple fade-out-and-in between two routes in sapper?

I鈥檓 Vie there is a simple wrapper component, and that鈥檚 it. Haven鈥檛 figured it out in svelte/sapper yet, however.

@rchrdnsh you could wrap your page in <div transition:fade style="position:absolute">...</div>

@buhrmi So how did you solve the old page not being removed? I can see that the code from your post works, but when I try to add animations myself that same issue arises. If I am to build my own site with this, I'd rather not depend on some unknown magic in your code, haha.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Rich-Harris picture Rich-Harris  路  3Comments

UnwrittenFun picture UnwrittenFun  路  4Comments

mylastore picture mylastore  路  3Comments

Rich-Harris picture Rich-Harris  路  4Comments

SARFEX picture SARFEX  路  3Comments