Skip to content
animorio
IT
Back to the library

The spiral notebook

Scroll, SVG, 3DGSAP, CSS onlyAdvancedCompressed weight: Demo 16 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

Scroll inside the preview

A spiral notebook lying open on the desk: as you scroll, the pages turn in 3D around the rings, bend and cast their shadow on the page below; on every new page a pen sketch draws itself, the notes write themselves by hand and sticky notes and paper clips land with a bounce.

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React tab holds the same demo as a ready component, which switches its animations off when it leaves the page.

<!doctype html>
<html lang="it">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Il quaderno ad anelli</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/caveat@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main>
    <!-- la scena: più alta dello schermo; il palco resta fermo e, scorrendo, le pagine si voltano -->
    <section class="scena" data-scena>
      <div class="palco" data-palco>
        <header class="testata">
          <p class="testata__marchio">Studio Pell <span>field notes</span></p>
          <p class="testata__titolo" data-titolo aria-live="polite"></p>
        </header>

        <!-- la vista in prospettiva: il piano del tavolo con il quaderno, e sopra una copia del piano con gli anelli -->
        <div class="vista" data-vista>
          <div class="piano" data-piano>
            <div class="tappetino" aria-hidden="true"></div>
            <!-- la matita e la gomma sul tavolo -->
            <svg class="matita" data-matita viewBox="0 0 300 26" aria-hidden="true">
              <path class="matita__ombra" d="M14 22 L262 22 L298 15 L262 8 L14 8 Z" />
              <path class="matita__gomma" d="M0 5 Q0 1 4 1 L22 1 L22 21 L4 21 Q0 21 0 17 Z" />
              <path class="matita__ghiera" d="M20 0 L38 0 L38 22 L20 22 Z" />
              <path class="matita__riga" d="M24 0 L24 22 M29 0 L29 22 M34 0 L34 22" />
              <path class="matita__corpo" d="M37 1 L246 1 L246 21 L37 21 Z" />
              <path class="matita__lato" d="M37 8 L246 8 L246 14 L37 14 Z" />
              <path class="matita__legno" d="M246 1 L284 9.5 Q288 11 284 12.5 L246 21 Z" />
              <path class="matita__mina" d="M276 7.8 L290 10.6 Q292 11 290 11.4 L276 14.2 Z" />
            </svg>
            <div class="gomma" data-gomma aria-hidden="true"><span>PELL</span></div>

            <!-- il quaderno: il cartone sotto, il cartone sopra (la copertina già girata) e le pagine -->
            <div class="cartone cartone--giu" aria-hidden="true"><div class="spessore" data-spessore></div></div>
            <div class="cartone cartone--su" aria-hidden="true">
              <div class="cartone__dentro">
                <p class="cartone__nome">Studio Pell</p>
                <p class="cartone__riga">Field notes, spring.</p>
                <p class="cartone__riga">If found, please return it to the studio.</p>
              </div>
              <div class="cartone__fori"></div>
              <div class="ombra" data-ombra-copertina></div>
            </div>
            <svg class="fili" data-fili aria-hidden="true"></svg>
            <div class="pagine" data-pagine></div>
            <svg class="anelli anelli--su" data-anelli-su aria-hidden="true"></svg>
          </div>
          <div class="piano piano--anelli" data-piano-anelli aria-hidden="true">
            <svg class="anelli anelli--giu" data-anelli-giu></svg>
          </div>
        </div>

        <p class="cenno" data-cenno>Scroll to leaf through the notebook</p>
      </div>
    </section>
  </main>

  <!-- le pagine del quaderno: uno schizzo in SVG per pagina, nell'ordine in cui si voltano.
       .t è un tratto di penna, .t.r di matita rossa, .nota una scritta a mano, .postit un post-it, .graffetta una graffetta -->
  <template data-pagina data-nome="Day one, the lighthouse">
    <svg class="schizzo" viewBox="0 0 568 400">
      <text class="nota nota--grande" x="44" y="86">Coast trip</text>
      <text class="nota" x="46" y="116">field notes, day one</text>
      <path class="t" d="M120 206 C119 192 131 182 144 182 C158 182 168 193 168 206 C168 220 157 230 144 230 C130 230 120 220 121 205" />
      <path class="t" d="M144 166 L144 156 M172 178 L180 171 M184 206 L194 206 M116 178 L108 171 M104 206 L94 206" />
      <text class="nota" x="102" y="262">first light, 6 am</text>
      <path class="t" d="M376 330 L386 152 L414 152 L424 330" />
      <path class="t" d="M380 152 L380 130 L420 130 L420 152 M376 152 L424 152" />
      <path class="t" d="M374 130 L400 108 L426 130 Z M400 108 L400 98" />
      <path class="t" d="M392 130 L392 152 M408 130 L408 152" />
      <path class="t r" d="M384 196 L416 196 L417 214 L383 214 Z M386 200 L414 210 M385 206 L405 213 M395 199 L415 205" />
      <path class="t r" d="M381 252 L419 252 L420 272 L380 272 Z M383 256 L417 268 M382 263 L405 271 M392 255 L418 262" />
      <path class="t" d="M396 300 L396 286 C396 282 404 282 404 286 L404 300" />
      <path class="t" d="M424 138 L506 114 M424 144 L510 156" />
      <path class="t" d="M318 346 C336 326 360 322 384 332 C404 322 430 318 460 330 C474 334 486 342 496 348" />
      <path class="t" d="M300 362 C314 354 328 366 342 360 C356 352 370 366 384 360 C398 352 412 366 426 360 C440 352 454 366 468 360 C482 352 496 366 512 358" />
      <path class="t" d="M236 82 C242 74 248 74 252 82 C256 74 262 74 268 82" />
      <path class="t" d="M272 108 C276 102 280 102 283 108 C286 102 290 102 294 108" />
      <path class="t" d="M300 262 C320 258 344 252 372 250 M362 244 L374 250 L364 258" />
      <text class="nota" x="204" y="290">red and white bands,</text>
      <text class="nota" x="204" y="314">keep for the poster?</text>
      <g class="postit postit--giallo" transform="translate(56 300) rotate(-5)">
        <path class="postit__ombra" d="M4 6 L124 4 L126 82 L6 86 Z" />
        <path class="postit__carta" d="M0 0 L120 0 L120 80 L0 80 Z" />
        <path class="postit__colla" d="M0 0 L120 0 L120 16 L0 16 Z" />
        <text class="postit__testo" x="12" y="40">pack the</text>
        <text class="postit__testo" x="12" y="64">good pens</text>
      </g>
    </svg>
  </template>

  <template data-pagina data-nome="The Pell chair, third try">
    <svg class="schizzo" viewBox="0 0 568 400">
      <text class="nota nota--grande" x="44" y="86">Pell chair, v3</text>
      <path class="t" d="M246 236 L372 236 L372 250 L246 250 Z" />
      <path class="t" d="M258 250 L246 352 M268 250 L258 352" />
      <path class="t" d="M358 250 L370 352 M368 250 L382 352" />
      <path class="t" d="M254 236 L234 118 M264 236 L246 118" />
      <path class="t" d="M228 120 C236 112 248 112 254 120 L256 152 C248 146 238 146 232 152 Z" />
      <path class="t" d="M252 312 L374 312" />
      <path class="t" d="M248 236 C280 228 330 228 372 236" />
      <path class="t" d="M206 236 L206 352 M200 236 L212 236 M200 352 L212 352" />
      <text class="nota" x="168" y="300">450</text>
      <path class="t" d="M246 372 L382 372 M246 366 L246 378 M382 366 L382 378" />
      <text class="nota" x="298" y="394">520</text>
      <path class="t" d="M470 98 C498 98 518 118 518 146 C518 174 498 194 470 194 C442 194 422 174 422 146 C422 118 442 98 470 98" />
      <path class="t" d="M440 132 L500 132 L500 146 L440 146 Z M462 146 L456 184 M478 146 L484 184 M468 126 L468 156" />
      <path class="t" d="M430 178 L372 238" />
      <text class="nota" x="424" y="222">dowel, no screws</text>
      <path class="t r" d="M396 316 C380 314 376 300 384 294 M378 300 L384 293 L392 298" />
      <text class="nota" x="402" y="324">legs thinner?</text>
      <path class="t r" d="M352 256 C350 290 356 330 364 356 M362 256 C366 300 372 330 378 356" />
      <g class="ritaglio" transform="translate(82 132) rotate(-6)">
        <path class="ritaglio__ombra" d="M4 5 L96 3 L98 76 L6 80 Z" />
        <path class="ritaglio__stoffa" d="M0 0 L92 0 L92 72 L0 72 Z" />
        <path class="ritaglio__trama" d="M6 10 L86 10 M6 20 L86 20 M6 30 L86 30 M6 40 L86 40 M6 50 L86 50 M6 60 L86 60 M14 4 L14 68 M30 4 L30 68 M46 4 L46 68 M62 4 L62 68 M78 4 L78 68" />
      </g>
      <text class="nota" x="80" y="240">wool, rust</text>
      <g class="graffetta" transform="translate(112 112) rotate(-6)">
        <path class="graffetta__filo" d="M6 50 L6 8 C6 2 18 2 18 8 L18 44 C18 50 12 50 12 44 L12 14" />
      </g>
    </svg>
  </template>

  <template data-pagina data-nome="The blue tile street">
    <svg class="schizzo" viewBox="0 0 568 400">
      <text class="nota nota--grande" x="44" y="86">Blue tile street</text>
      <path class="t" d="M150 360 L150 132 L420 132 L420 360" />
      <path class="t" d="M138 132 L432 132 M142 122 L428 122 L432 132" />
      <path class="t" d="M178 210 L178 168 C178 150 210 150 210 168 L210 210 Z" />
      <path class="t" d="M268 210 L268 168 C268 150 300 150 300 168 L300 210 Z" />
      <path class="t" d="M358 210 L358 168 C358 150 390 150 390 168 L390 210 Z" />
      <path class="t" d="M256 222 L312 222 M260 222 L260 240 M270 222 L270 240 M280 222 L280 240 M290 222 L290 240 M300 222 L300 240 M308 222 L308 240 M256 240 L312 240" />
      <path class="t" d="M178 300 L178 262 C178 244 210 244 210 262 L210 300 Z" />
      <path class="t" d="M358 300 L358 262 C358 244 390 244 390 262 L390 300 Z" />
      <path class="t" d="M262 360 L262 270 C262 246 306 246 306 270 L306 360 M284 254 L284 360" />
      <path class="t" d="M150 318 L262 318 M306 318 L420 318" />
      <path class="t" d="M156 330 L164 322 L172 330 L164 338 Z M180 330 L188 322 L196 330 L188 338 Z M204 330 L212 322 L220 330 L212 338 Z M228 330 L236 322 L244 330 L236 338 Z M324 330 L332 322 L340 330 L332 338 Z M348 330 L356 322 L364 330 L356 338 Z M372 330 L380 322 L388 330 L380 338 Z M396 330 L404 322 L412 330 L404 338 Z" />
      <path class="t" d="M156 350 L164 342 L172 350 M180 350 L188 342 L196 350 M204 350 L212 342 L220 350 M228 350 L236 342 L244 350 M324 350 L332 342 L340 350 M348 350 L356 342 L364 350 M372 350 L380 342 L388 350 M396 350 L404 342 L412 350" />
      <path class="t r" d="M174 154 C170 140 196 132 214 146 C222 156 216 170 204 168" />
      <path class="t" d="M120 168 C140 170 158 164 172 160 M162 154 L174 159 L164 167" />
      <text class="nota" x="40" y="196">arches,</text>
      <text class="nota" x="40" y="220">a logo?</text>
      <path class="t" d="M110 300 C124 316 136 324 150 330 M138 318 L151 331 L136 334" />
      <text class="nota" x="36" y="290">tiles, four colours</text>
      <g class="postit postit--rosa" transform="translate(440 222) rotate(5)">
        <path class="postit__ombra" d="M4 6 L112 4 L114 82 L6 86 Z" />
        <path class="postit__carta" d="M0 0 L108 0 L108 80 L0 80 Z" />
        <path class="postit__colla" d="M0 0 L108 0 L108 16 L0 16 Z" />
        <text class="postit__testo" x="10" y="40">come back</text>
        <text class="postit__testo" x="10" y="64">at dusk</text>
      </g>
    </svg>
  </template>

  <template data-pagina data-nome="A fig leaf from the market">
    <svg class="schizzo" viewBox="0 0 568 400">
      <text class="nota nota--grande" x="44" y="86">Fig leaf, market</text>
      <path class="t" d="M300 300 C272 306 240 300 222 282 C200 292 172 288 158 268 C176 258 188 246 194 232 C170 230 148 214 144 190 C168 196 190 192 204 182 C190 162 192 136 208 116 C222 134 238 148 254 154 C258 132 274 110 300 96" />
      <path class="t" d="M300 96 C326 110 342 132 346 154 C362 148 378 134 392 116 C408 136 410 162 396 182 C410 192 432 196 456 190 C452 214 430 230 406 232 C412 246 424 258 442 268 C428 288 400 292 378 282 C360 300 328 306 300 300" />
      <path class="t" d="M300 300 C302 320 306 340 316 364" />
      <path class="t" d="M300 296 C300 240 301 160 300 104" />
      <path class="t" d="M300 250 C270 240 232 222 204 200 M300 250 C330 240 368 222 396 200" />
      <path class="t" d="M300 196 C282 180 264 166 252 158 M300 196 C318 180 336 166 348 158" />
      <path class="t" d="M300 280 C272 282 244 278 222 272 M300 280 C328 282 356 278 378 272" />
      <path class="t" d="M252 230 L236 246 M348 230 L364 246 M268 186 L254 200 M332 186 L346 200" />
      <path class="t" d="M64 312 L94 312 L94 342 L64 342 Z M68 316 L90 338 M68 326 L80 338 M74 316 L90 332" />
      <path class="t" d="M108 312 L138 312 L138 342 L108 342 Z M112 322 L134 322 M112 330 L134 330" />
      <path class="t" d="M152 312 L182 312 L182 342 L152 342 Z M156 316 L178 338 M156 324 L170 338 M162 316 L178 332 M156 332 L164 338 M170 316 L178 324" />
      <text class="nota nota--piccola" x="62" y="364">olive</text>
      <text class="nota nota--piccola" x="108" y="364">sand</text>
      <text class="nota nota--piccola" x="154" y="364">ink</text>
      <path class="t r" d="M146 318 C140 300 168 296 184 304 C196 314 190 346 172 350 C156 352 146 344 146 330" />
      <text class="nota" x="420" y="330">wrapping paper</text>
      <text class="nota" x="420" y="354">print, maybe</text>
      <path class="t" d="M446 312 C440 298 428 290 412 282 M416 292 L410 281 L423 280" />
      <g class="postit postit--giallo" transform="translate(436 104) rotate(-4)">
        <path class="postit__ombra" d="M4 6 L104 4 L106 82 L6 86 Z" />
        <path class="postit__carta" d="M0 0 L100 0 L100 80 L0 80 Z" />
        <path class="postit__colla" d="M0 0 L100 0 L100 16 L0 16 Z" />
        <text class="postit__testo" x="10" y="40">ask Ines</text>
        <text class="postit__testo" x="10" y="64">about paper</text>
      </g>
    </svg>
  </template>

  <template data-pagina data-nome="Last morning, then home">
    <svg class="schizzo" viewBox="0 0 568 400">
      <text class="nota nota--grande" x="44" y="86">Last morning</text>
      <path class="t" d="M136 334 C136 316 324 316 324 334 C324 352 136 352 136 334 Z" />
      <path class="t" d="M174 252 C176 302 194 330 230 330 C266 330 284 302 286 252" />
      <path class="t" d="M174 252 C174 240 286 240 286 252 C286 264 174 264 174 252 Z" />
      <path class="t" d="M284 268 C316 262 320 302 278 306" />
      <path class="t" d="M206 230 C196 210 216 200 206 180 M230 228 C220 204 242 194 230 168 M254 230 C246 212 264 202 254 186" />
      <path class="t" d="M190 284 C200 296 214 302 228 304" />
      <text class="nota" x="364" y="124">to do back home</text>
      <text class="nota" x="364" y="164">poster, the lighthouse</text>
      <text class="nota" x="364" y="198">chair, thinner legs</text>
      <text class="nota" x="364" y="232">tile print samples</text>
      <text class="nota" x="364" y="266">call the printer</text>
      <path class="t" d="M360 158 C420 155 470 157 530 154" />
      <path class="t" d="M360 192 C410 190 450 192 504 189" />
      <path class="t" d="M360 226 C400 224 440 226 492 222" />
      <path class="t r" d="M356 280 C400 276 450 282 494 276" />
      <g class="biglietto" transform="translate(48 116) rotate(-4)">
        <path class="biglietto__ombra" d="M4 5 L176 3 L178 66 L6 70 Z" />
        <path class="biglietto__carta" d="M0 0 L172 0 L172 62 L0 62 Z" />
        <path class="biglietto__strappo" d="M132 4 L132 58" />
        <text class="biglietto__testo" x="12" y="26">TRAIN 08:14</text>
        <text class="biglietto__testo biglietto__testo--piccolo" x="12" y="46">COAST TO CITY</text>
      </g>
      <g class="graffetta" transform="translate(64 96) rotate(-4)">
        <path class="graffetta__filo" d="M6 50 L6 8 C6 2 18 2 18 8 L18 44 C18 50 12 50 12 44 L12 14" />
      </g>
      <g class="postit postit--rosa" transform="translate(410 296) rotate(-3)">
        <path class="postit__ombra" d="M4 6 L112 4 L114 82 L6 86 Z" />
        <path class="postit__carta" d="M0 0 L108 0 L108 80 L0 80 Z" />
        <path class="postit__colla" d="M0 0 L108 0 L108 16 L0 16 Z" />
        <text class="postit__testo" x="12" y="40">ship it</text>
        <text class="postit__testo" x="12" y="64">on Friday</text>
      </g>
    </svg>
  </template>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.

29 values to change

Or ask Claude Code for it

With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:

Take “The spiral notebook” from Animorio and fit it into my site

What it does

On a green cutting mat lies an open spiral notebook, seen a little from above, with a pencil and an eraser next to it. At the top is the cardboard cover, already turned, with a handwritten note saying whose it is; at the bottom the first page, ruled, and between them the metal spiral, with the rings coming out of the holes of one page, passing over the spine and going back into the holes of the other. It is the travel notebook of a made-up studio, Studio Pell. As soon as the page shows, a pen sketch draws itself, stroke after stroke, gone over twice the way a hand does: a lighthouse on the rocks, with its bands coloured in red pencil; the notes write themselves letter by letter and a yellow sticky note drops onto the page and bounces. As you scroll, the page lifts off the pile, rises bending a little, stands up over the rings and falls on the other side, where it flaps and bounces two or three times; while it rises its shadow runs over the page below and shrinks back towards the spine, then shows up again on the turned pile. Of the turned page you see the back, with the sketch showing through in reverse. Underneath is the new page, which draws itself in turn: the studio chair with its measurements, a fabric swatch and a paper clip; a building front with arches and tiles; a fig leaf with colour swatches; the last morning with the cup, the train ticket and the to-do list, crossed out one by one. At the top the title of the open page changes with jumping letters. Scrolling back up the pages turn backwards and the covered ones are wiped, so they draw themselves again. With a mouse, the sticky notes lift when you hover over them.

How it works

The desk in perspective

The stage is sticky, 100lvh tall, inside a section a few screens tall. The desk is a big plane, with perspective on its parent and rotateX to see it from above: the mat, the pencil, the eraser, the two cardboard covers and the pages sit on it with transform-style: preserve-3d. The sizes (page width, spine gap, ring pitch) are worked out by the script from the window and written as CSS variables, so the notebook always fits between the header and the hint, on a phone too.

A page in three strips

Each page is made of three nested strips: the first turns around the spine (transform-origin moved half a spine above its edge), the other two turn back a little relative to the one carrying them. That is how the page bends: the extra angle is CURL times sin(π·p) and goes to zero when the page lies flat, below or above. Each strip has a front and a back (backface-visibility: hidden, the back with rotateX(180deg)) and both hold the whole sheet, moved up to show the right slice. A dark veil on each face follows the tilt of its strip: that is the light.

Rings in front and behind

A ring is a circle around the spine. Seen from above, a point lifted z above the paper appears shifted towards the far side by z·tan(tilt): that is how the script draws the arc on the plane, from the lower hole, over the spine, to the upper hole; under the paper the wire goes back and only shows in the spine gap. The half over the turned pages lives in the notebook, lifted a little, so a standing page hides it; the half over the pages still to turn lives in a twin plane with the same transform, drawn in front of everything.

Scrolling and the shadow

Lenis smooths the scroll and a timeline with ScrollTrigger (scrub) drives a number from 0 to 1 for each page, with a pause between pages. On every update the page gets its angle, bend and height (translateZ, to sit on top of the right pile) and the page below gets its shadow: a gradient from the spine, H·cos(angle) long, strong while the page is low. When the page touches the pile a small timed bounce (bounce.out) is added to the angle and makes the edge flap.

The sketch that draws itself

The sketches are SVGs in the page’s templates. Every stroke has pathLength=1 and a second, slightly shifted pass; it draws by taking stroke-dashoffset from 1 to 0, over a time that grows with its real length. The notes are split into tspans and appear letter by letter with fill-opacity; sticky notes and paper clips drop with back.out and elastic.out. The drawing starts when the page above is half turned, finishes quickly if the page starts turning before it is done and resets when it is covered again. SPEED changes the timeScale.

Values to change

NameFileDefaultWhat it changes
PAGESscript.js5How many pages the notebook has, from 2 to 5 (one per sketch): the last one stays open, the others turn.
CURLscript.js1How much the page bends while it turns: 0 is stiff like card, 2 very soft.
PAPERscript.js'lines'The paper of the pages: 'lines' ruled with a red margin, 'grid' squared, 'blank' plain.
INKscript.js'#22305c'The pen colour of the sketches and notes.
SPEEDscript.js1How fast the sketches draw themselves: 2 is twice as fast, 0.5 half as fast.
TILTscript.js30How much we see the notebook from above, in degrees: 0 is head-on, 45 strongly tilted.

Try them in the Playground

When to use it

To tell a process or a journey one step at a time: a studio’s “how we work” page, a project diary, a sketch portfolio, the site of a stationery shop or a notebook maker, a case study that shows the ideas before the result.

On phones

The same animation with the sizes adapted: the notebook is almost as wide as the screen, the perspective is longer so the standing page does not spill over the sides, and the pencil and eraser lie under the notebook instead of beside it.

With reduced motion

No lifting pages and no smooth scrolling: the sketches are already drawn and, as you scroll, the page fades away and reappears turned at the top, showing the new one underneath.

Pitfalls

  • An element with preserve-3d loses its depth if it has opacity, overflow, filter or clip-path: the strips stay clean and the reduced-motion fade acts on the faces, which have no 3D children.
  • Rings drawn entirely over the pages pierced the standing page; entirely inside the notebook, they were cut by the page lifting off. They are split in half: the half towards the turned pages lives in the notebook, the other in a twin plane in front of everything, with the same transform and the same height, so the two halves meet.
  • The bend pushes the first strip past the page angle: near 0° or 180° it would have gone into the pile. The bend is sin(π·p), so it vanishes at the ends, and every angle is clamped between 0 and 180 anyway; the bounce bends the free edge too, never the part near the rings.
  • With pathLength=1 and round caps, a stroke not yet drawn leaves a dot: strokes start at opacity 0 and switch on only when they start drawing.
  • The pencil's CSS rotate was wiped by GSAP's inline transform: GSAP writes the resting rotation itself, and the nudge starts from there.
  • Each page exists three times (one per strip): every stroke, letter and sticky note animates on all three copies together, found by the same data-k.

Libraries

GSAP 3.15.0, Lenis 1.3.26, Caveat (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 16 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.

Testing

Tested on 10 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: To do

License

Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.

All animations