Skip to example

Scroll progress

An example of using Motion's scroll function in Svelte to link a progress bar to the page scroll. scroll() returns a cleanup function, so it works as an attachment.

Svelte

Source code

<script>
  import { animate, scroll } from "motion"

  function scrollProgress(element) {
    return scroll(animate(element, { scaleX: [0, 1] }, { ease: "linear" }))
  }
</script>

<div class="progress" {@attach scrollProgress}></div>

<article>
  {#each { length: 5 }, i}
    <section>
      <h2>Section {i + 1}</h2>
      <p>
        The bar at the top of the page follows the scroll position. scroll()
        drives the animation with a ScrollTimeline where the browser supports
        it, so it runs off the main thread.
      </p>
    </section>
  {/each}
</article>

<style>
  :global(body) {
    overflow-x: hidden;
    overflow-y: scroll;
  }

  .progress {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 10px;
    background-color: var(--hue-2);
    transform-origin: 0 50%;
    transform: scaleX(0);
  }

  article {
    box-sizing: border-box;
    width: min(100vw, 560px);
    margin-inline: auto;
    padding: 64px 24px;
  }

  section {
    min-height: 70vh;
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding-bottom: 64px;
  }

  h2 {
    margin: 0;
    color: var(--hue-2);
    line-height: 1.1;
    text-wrap: balance;
  }

  p {
    margin: 0;
    line-height: 1.6;
  }
</style>