DEV Community

Cover image for Animate on scroll with Svelte Inview - Little Bits
Maciek Grzybek
Maciek Grzybek

Posted on • Updated on


Animate on scroll with Svelte Inview - Little Bits

Little Bits is a series of short articles explaining quick solutions to common dev problems. No unnecessary descriptions or code snippets. No bullshit.

In this episode, I want to show you how you can animate elements in your Svelte app on scroll.


When user is scrolling your Svelte app/website, we want to animate the entering elements to get that extra fancy feel.

Gif showing the scroll animation

The best solution is to use Intersection Observer, but we can also use a nice abstraction built on top of it - svelte-inview. This is a small library I created some time ago that greatly simplify usage of the IO API. Let's see how we can do this.


Create an app with Vite

Let's use Vite to create a simple Svelte App:

npm create vite@latest my-svelte-app -- --template svelte

cd my-svelte-app

npm i

npm run dev
Enter fullscreen mode Exit fullscreen mode

Add scaffolding

Let's add some simple app with basic styling. Paste that code in your App.svelte file:

  import AnimatedElement from './lib/AnimatedElement.svelte';

  <div class="hero">
    <h1>Hello Svelte Inview</h1>
    <p>Scroll down to animate the elements</p>
  <div class="full-height">
    <AnimatedElement />
  <div class="full-height">
    <AnimatedElement />

  :root {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
      Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;

  main {
    text-align: center;
    padding: 0 1em;
    margin: 0 auto;

  h1 {
    margin-bottom: 0.5rem;

  p {
    margin-top: 0;

  .hero {
    height: calc(100vh - 16px);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;

  .full-height {
    height: 100vh;
    display: flex;
    justify-content: center;
Enter fullscreen mode Exit fullscreen mode

You probably notice that we import the AnimatedElement component - we will create it in the next step.

Add AnimatedElement component

Create a file called AnimatedElement.svelte and add this code:

<script lang="ts">
  import { fade } from 'svelte/transition';
  import { inview } from 'svelte-inview';

  let isInView;

  use:inview={{ unobserveOnEnter: true, rootMargin: '-20%' }}
  on:change={({ detail }) => {
    isInView = detail.inView;
  {#if isInView}
    <div in:fade class="box">
      <h3>Appears from nowhere</h3>
        Lorem ipsum, dolor sit amet consectetur adipisicing elit. Error,
        adipisci nihil iste.

  .wrapper {
    margin-top: 30px;

  .box {
    width: 300px;
    border: 1px solid rgb(221, 221, 221);
    padding: 25px;
    border-radius: 10px;
Enter fullscreen mode Exit fullscreen mode

What is going on here?
First we import the inview action and animation from svelte.

Then we assign the action to the wrapper with some options:

  • unobserveOnEnter: true - this means that once element is on the screen and animated, it won't be animated again
  • `rootMargin: '-20%' - this means that element will be considered "on screen" once it'll reach 20% of the monitor - better explanation here

Next step is to handle the element entry - we assign the inView flag from the action to our local variable - isInView. This allows us to determine if element should be animated.

Then we check if isInView is true, if it is we animate the element into view by adding the in:fade action.

Useful links

Top comments (5)

val1nk profile image
Valentin SOURICE

Awesome lib, thank you for sharing.

However this approach enforces you to wrap any of the stuff you want to animate into a component (here : AnimatedElement).
Is there any other way to integrate animation on scroll without this ?

maciekgrzybek profile image
Maciek Grzybek

Not sure what do you mean? It doesn't have to be a component. You can attach this action to any DOM element you want.

ucielsola profile image

Very usefull! I've been doing this kind of things by hand.

benzaratahar profile image
Benzara Tahar Benlahcene

Although it might work, but it seems ugly ( enforces parent wrapper, variable for each element i want to animate)
I think it should be just doable using some svelte actions combined with some global styles for for animations

maciekgrzybek profile image
Maciek Grzybek

Well, it's very opinionated :) I don't think it's ugly :) It doesn't enforce the wrapper, it's just an approach I took here to make it more readable. Also, can you elaborate on variable for each element i want to animate? No idea what do you mean here :)

I think it should be just doable using some svelte actions combined with some global styles for for animations - please, do show me how would you handle that :)

Timeless DEV post...

Git Concepts I Wish I Knew Years Ago

The most used technology by developers is not Javascript.

It's not Python or HTML.

It hardly even gets mentioned in interviews or listed as a pre-requisite for jobs.

I'm talking about Git and version control of course.

One does not simply learn git