Add Transition Effects to a Svelte App

John Au-Yeung - Jan 28 '21 - - Dev Community

Check out my books on Amazon at https://www.amazon.com/John-Au-Yeung/e/B08FT5NT62

Subscribe to my email list now at http://jauyeung.net/subscribe/

Svelte is an up and coming front end framework for developing front end web apps.

It’s simple to use and lets us create results fast.

In this article, we’ll look at how to add transition effects to a Svelte app.

Transitions

Svelte has built-in libraries for adding transitions. We can add the fade function to create a fade effect.

To use it, we write the following code:

App.svelte :

<script>
  import { fade } from "svelte/transition";
  let visible = true;
</script>

<button on:click={() => visible = !visible}>Toggle</button>
{#if visible}
<p transition:fade>foo</p>
{/if}
Enter fullscreen mode Exit fullscreen mode

In the code above, we toggle visible between true and false as we click the Toggle button.

Then the p element fades as it’s being toggle on and off.

Transition functions can accept parameters. For instance, we can modify the default options of the fly effect as follows:

App.svelte :

<script>
  import { fly } from "svelte/transition";
  let visible = true;
</script>

<button on:click={() => visible = !visible}>Toggle</button>
{#if visible}
<p transition:fly="{{ y: 200, duration: 3000 }}">foo</p>
{/if}
Enter fullscreen mode Exit fullscreen mode

The code above moved the word foo up and down as we click the Toggle button. y indicates the distance that we move the word foo up and down. duration is the length of the transition effect.

We should therefore then see the word foo move up and down as we click the Toggle button.

With Svelte, we can also only add transition effects when an item is added to the DOM with the in directive, and animate when the item is removed from the DOM with the out directive.

For instance, we can write the following:

App.svelte :

<script>
  import { fade } from "svelte/transition";
  let visible = true;
</script>

<button on:click={() => visible = !visible}>Toggle</button>
{#if visible}
<p in:fade="{{ y: 200, duration: 3000 }}">foo</p>
{/if}
Enter fullscreen mode Exit fullscreen mode

The code above only applies the fade effect when the p element with word foo is being inserted into the DOM. We should see a fade effect at that time.

Likewise, we can use the out directive to only add transition effect when the p element is removed from the DOM as follows:

<script>
  import { fade } from "svelte/transition";
  let visible = true;
</script>

<button on:click={() => visible = !visible}>Toggle</button>
{#if visible}
<p out:fade="{{ y: 200, duration: 3000 }}">foo</p>
{/if}
Enter fullscreen mode Exit fullscreen mode

Creating our own Transition

We can create our own transitions if we don’t want to use the built-in transitions.

For instance, we can write the following code to create an effect that spins the text and change the color as the p element is being removed from the DOM a follows:

<script>
  import { fade } from "svelte/transition";
  import { elasticOut } from "svelte/easing";
  let visible = true;

  const spin = (node, { duration }) => {
    return {
      duration,
      css: t => {
        const eased = elasticOut(t);

        return `
            transform: scale(${eased}) rotate(${eased * 1080}deg);
            color: hsl(
              ${~~(t * 360)},
              ${Math.min(100, 2000 - 1000 * t)}%,
              ${Math.min(50, 2000 - 500 * t)}%
            );`;
      }
    };
  };
</script>

<button on:click={() => visible = !visible}>Toggle</button>
{#if visible}
<p out:spin="{{ y: 200, duration: 3000 }}">foo</p>
{/if}
Enter fullscreen mode Exit fullscreen mode

Add we did was return the CSS for styling the p element as the time t is increasing.

elasticOut defines our easing, which is our rate of change over time. We passed it into transform to change the size of the text. We also used it to change the rotation angle of the text as it fades out.

JavaScript Animation

We can also animate text with JavaScript. For instance, we can create a typewriter effect as follows:

<script>
  let visible = true;

  const typewriter = (node, { speed = 50 }) => {
    const valid =
      node.childNodes.length === 1 && node.childNodes[0].nodeType === 3;

    if (!valid) {
      return;
    }

    const text = node.textContent;
    const duration = text.length * speed;

    return {
      duration,
      tick: t => {
        const i = Math.ceil(text.length * t);
        node.textContent = text.slice(0, i);
      }
    };
  };
</script>

<button on:click={() => visible = !visible}>Toggle</button>
{#if visible}
<p in:typewriter>Hello Jane. How are you?</p>
{/if}
Enter fullscreen mode Exit fullscreen mode

In the code above, we created the typewriter effect by defining a typewriter function.

We progressive append the text content into the p element as time goes on, which means t is increasing.

Therefore, we’ll get a typewriter when we toggle the text on by clicking the Toggle button since we have:

<p in:typewriter>Hello Jane. How are you?</p>
Enter fullscreen mode Exit fullscreen mode

in the markup.

Conclusion

Svelte has built-in libraries for creating transitions and animations. It makes animation effects easy.

We just import the functions for animation and apply them with in , out , or transition directives.

Also, we can make our own custom animations by writing our own animation functions applying them with the same directives.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .