animationsveltesveltekitcross-fade

Svelte crossfade animation only works when imported from different file


I am using a crossfade animation in svelte, but If I directly implement the logic in the same page(like below) the fallback animation will trigger(which is not expected behavior). But if I put the crossfade in different .js file and import it, the animation works perfectly fine.

<script>
  import { quintOut } from "svelte/easing";
  import { crossfade } from "svelte/transition";
  export let todos;
  export let done;

  export const [send, receive] = crossfade({
    duration: 300,
    fallback(node, params) {
      const style = getComputedStyle(node);
      const transform = style.transform === "none" ? "" : style.transform;

      return {
        duration: 600,
        easing: quintOut,
        css: (t) => `
            transform: ${transform} scale(${t});
            opacity: ${t}
        `,
      };
    },
  });
</script>

<ul>
  {#each $todos.filter((/** @type {{ done: any; }} */ todo) => todo.done === done) as todo (todo.id)}
    <label>
      <li class:done in:receive={{ key: todo.id }} out:send={{ key: todo.id }}>
        <input
          type="checkbox"
          checked={todo.done}
          on:change={(e) => todos.mark(todo, e.currentTarget.checked)}
        />
        <span>{todo.description}</span>
      </li>
    </label>
  {/each}
</ul>

<style>
  .done {
    opacity: 0.6;
    text-decoration: line-through;
  }

  ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
    width: 100%;
  }

  li {
    padding: 1rem;
    margin: 1.3rem;
    font-size: 1.2rem;
    box-shadow: 0 3px 10px rgb(0 0 0 / 0.2);
    border-radius: 3px;
  }
</style>

Solution

  • This is expected. If the transitions are defined as part of the component script, there will be separate instances for each component instance, i.e. the components will be disconnected.

    You don't necessarily need a separate file, but can also move the definitions to the <script context="module"> (<script module> in Svelte 5).