data-scroll-draw · initScrollDraw()

Astro scroll animation

Astro’s whole premise is shipping no JavaScript unless you ask for it, so a component wrapper that forces hydration would defeat the point. Here the markup stays a server component: mark elements with data-scroll-draw, pass options as a JSON attribute, and call initScrollDraw() once from a client script. One small script for the whole page, no island per animation.

The code

Zero-JS server components — add data-scroll-draw to any element and call initScrollDraw() in a client script. Options are passed as a JSON attribute. No framework wrapper needed.

Hero.tsx
// src/pages/index.astro
---
// No server-side imports needed
---

<div
  data-scroll-draw
  data-scroll-draw-options='{"easing":"ease-out","fade":true,"once":true}'
>
  <svg viewBox="0 0 200 80" fill="none">
    <path d="M10 40 Q100 5 190 40"
      stroke="white" strokeWidth="2" />
  </svg>
</div>

<script>
  import { initScrollDraw } from 'svg-scroll-draw/astro';

  // Finds all [data-scroll-draw] on the page and
  // initialises each one — no React, no Vue needed.
  initScrollDraw();
</script>

Live — scroll it

src/pages/index.astro
<div data-scroll-draw
data-scroll-draw-options='{"easing":"ease-out","once":true}'
>
<svg viewBox="0 0 200 80">
<path d="M10 40 Q100 5 190 40"
stroke="white" fill="none" />
</svg>
</div>
<script>
import { initScrollDraw } from 'svg-scroll-draw/astro';
initScrollDraw();
</script>

Install

terminal
npm i svg-scroll-draw

MIT licensed, zero runtime dependencies. Every API is a separate entry point, so you only ship what you import. Full API reference →