how to animate:flip with in/out:fade?

368 views Asked by At

I am trying to animate a changing list of elements, where some disappear, some move, and some appear.

Ideal animation sequence:

  1. Old elements fade out
  2. Existing elements move from old position to new position
  3. New elements fade in

The problem (bug?) is that the old elements, as they fade out, appear stacked on top of each other at the top or bottom of the list.

Can I not use animate:flip and transition:fade (in/out shorthand) at the same time?

REPL: https://svelte.dev/repl/5feb66e2ac544e10a11b98890c1b24dd?version=3.55.1

Code here for completeness:

<script>
    import { flip } from 'svelte/animate'
    import { fade } from 'svelte/transition'
    
    let startInt = 0
    $:items = Array(5).fill().map((x,i) => i+startInt)
    function shiftDown() {
        startInt = startInt + 3
    }
    function shiftUp() {
        startInt = startInt - 3
    }
</script>

<a href="#" on:click|preventDefault="{e => shiftUp()}">up</a>

{#each items as item (item)}
    <div
             animate:flip="{{delay: 1000, duration: 1000}}"
             in:fade="{{delay: 2000, duration: 1000}}"
             out:fade="{{duration: 1000}}"
    >
        {item}
    </div>
{/each}

<a href="#" on:click|preventDefault="{e => shiftDown()}">down</a>

List of items with buddy fade out

1

There are 1 answers

2
Corrl On BEST ANSWER

Wrapping the elements in a container with display: flex seems to solve the problem

REPL

<script>
    import { flip } from 'svelte/animate'
    import { fade } from 'svelte/transition'

    let startInt = 0
    $:items = Array(5).fill().map((x,i) => i+startInt)
    
    function shiftDown() {
        startInt = startInt + 3
    }
    function shiftUp() {
        startInt = startInt - 3
    }
</script>

<button on:click={shiftUp}>up</button>

<div id="wrapper">
    {#each items as item (item)}
    <div
             animate:flip="{{delay: 1000, duration: 1000}}"
             in:fade="{{delay: 2000, duration: 1000}}"
             out:fade="{{duration: 1000}}"
             >
        {item}
    </div>
    {/each}
</div>

<button on:click={shiftDown}>down</button>

<style>
    #wrapper {
        display: flex;
        flex-direction: column;
    }
</style>