Search code examples
sveltegsap

Using GSAP with svelte


I'm having trouble using GSAP in my svelte project for a CV based site. I'm relatively new to both. I understand that svelte has its own animation library but I was wanting to use GSAP for its timeline capabilities. As a test I tried changing the colour of a blue square but couldn't seem to get it to work. It either wouldn't change or wouldn't be there at all. I've installed GSAP as a dependency too. This is the code in my App.svelte:

<script>
    import { gsap } from "gsap";
    gsap.from(".blue", {color: "#8c0", duration: 1});
</script>

<main>
    <div class="blue"></div>
</main>

<style>
  .blue {
        width: 100px;
        height: 100px;
        background-color: blue;
    }
</style>

I also tried using the from method but have had no luck there either. Any help would be really appreciated.


Solution

  • The contents of <script> run before the DOM is created (since Svelte often doesn't know what DOM it needs to create until the code has run). If you need to do something with the DOM that has been created, you have to wait until it has been mounted, which you do with the onMount lifecycle function:

    <script>
        import { gsap } from "gsap";
        import { onMount } from "svelte";
    
        onMount(() => {
            gsap.from(".blue", {color: "#8c0", duration: 1});
        });
    </script>
    
    <main>
        <div class="blue"></div>
    </main>
    
    <style>
        .blue {
            width: 100px;
            height: 100px;
            color: blue;
            background-color: currentColor;
        }
    </style>
    

    (Note: I changed background-color to use currentColor, since animating the color has no effect otherwise.)

    In Svelte, it's preferable not to use global selectors like .blue, because if you have multiple instances of this component GSAP won't just select the element belonging to this component. It's better to pass in a DOM element directly. You can get a reference to the element with bind:this:

    <script>
        import { gsap } from "gsap";
        import { onMount } from "svelte";
    
        let box;
    
        onMount(() => {
            gsap.from(box, {color: "#8c0", duration: 1});
        });
    </script>
    
    <main>
        <div bind:this={box} class="blue"></div>
    </main>
    
    <style>
        .blue {
            width: 100px;
            height: 100px;
            color: blue;
            background-color: currentColor;
        }
    </style>
    

    Demo here.