# Svelte(Kit): Making a reusable 'Animate On Scroll (once visible)' component

Ever needed to animate in an element once it's visible on the screen?  There are multiple ways to achieve this, with even more ways to handle the animation.  I'm using 
[`svelte-intersection-observer`](https://www.npmjs.com/package/svelte-intersection-observer) to track when the element is in view, and TailwindCSS classes for the animations.

## Check out the code: `<AnimatedElement>`
```svelte
<script>
  import IntersectionObserver from "svelte-intersection-observer";

  let element;
  let intersecting;

  export let duration = "700ms";
  export let delay = "0";
  export let fade = false;
  export let fly = false;
  export let offset = "0";
  export let once = true;

  // Set the default to fly if 'fly' or 'fade' are not specified
  fly = !fade && !fly ? true : false;
</script>

<IntersectionObserver
  rootMargin={`${offset}px`}
  {once}
  {element}
  bind:intersecting
>
  {#if fade}
    <div
      bind:this={element}
      class={`${intersecting ? "opacity-100" : "opacity-0"} transition`}
      style="transition-delay: {delay}; transition-duration: {duration}"
    >
      <slot {intersecting} />
    </div>
  {/if}

  {#if fly}
    <div
      bind:this={element}
      class={`${
        intersecting ? "opacity-100 translate-y-0" : "opacity-0 -translate-y-6"
      } transform transition`}
      style="transition-delay: {delay}; transition-duration: {duration}"
    >
      <slot {intersecting} />
    </div>
  {/if}
</IntersectionObserver>
```

I know this code could be shortened, but I'm not that concerned with that.  I'd rather have a component I can easily read.  Also note, I'm passing `intersecting` back into the slot, in case you need the trigger wherever you use the component

## How to use:
```svelte
<AnimatedElement>
   <a href="/">
      <img src="/img/logo.svg" class="h-16 md:h-20 lg:h-auto" alt="logo" />
    </a>
</AnimatedElement>
```

## Potential improvements
I didn't have time to lollygag when coding this, but I would like to make this without needing the extra wrapper div inside the `<AnimatedElement>` component.  I don't see why this wouldn't be possible by using the `<svelte:element this={tag}>` tag and passing the element `tag` along with the `class` into the component.  Like this `<AnimatedElement tag="div" class="flex">`.  Let me know you'd like for me to code that out.

Thanks for reading!  Now go grab some pizza!
