Skip to content
animorio
IT
Back to the library

The dig on scroll

Scroll, SVGGSAPAdvancedCompressed weight: Demo 20 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

Scroll inside the preview

A slice of ground seen from the side: as you scroll you go down through grass and roots, loam, clay, gravel and rock. In every layer a shovel digs, throws the earth away a shovelful at a time, and a find comes out of the hole: a coin that flips, a jar that puts itself back together, an arrowhead, an ammonite that draws its coil and a dinosaur skeleton that builds itself bone by bone. The museum label swings in next to it, and a ruler on the side shows the depth.

The code

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

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Lo scavo allo scroll</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main>
    <!-- the opening of the made-up museum -->
    <section class="apertura">
      <header class="testata">
        <p class="marchio" data-entra>Underfield <span>Museum</span></p>
        <nav class="menu" aria-label="Main" data-entra>
          <a href="#scavo">The trench</a>
          <a href="#fine">Visit</a>
        </nav>
      </header>
      <p class="apertura__etichetta" data-entra>Gallery of the Ground</p>
      <h1 class="apertura__titolo">
        <span class="riga"><span data-titolo>Twelve metres</span></span>
        <span class="riga"><span data-titolo>of <em>buried time.</em></span></span>
      </h1>
      <p class="apertura__testo" data-entra>One trench, five layers, five finds. Grab the shovel: every turn of the wheel digs a little deeper.</p>
      <p class="apertura__cenno" data-entra>
        Scroll to dig
        <svg viewBox="0 0 24 32" aria-hidden="true"><path d="M12 3V27M4 19L12 28L20 19" /></svg>
      </p>
    </section>

    <!-- the trench: the stage stays still and the ground moves up as we dig down -->
    <section class="scavo" id="scavo" data-scavo>
      <div class="palco" data-palco>
        <svg class="terreno" data-terreno viewBox="0 -400 1200 760" preserveAspectRatio="xMidYMid slice" aria-label="A cross-section of the ground, with a find in every layer" role="img">
          <defs>
            <linearGradient id="grad-cielo" x1="0" y1="0" x2="0" y2="1">
              <stop offset="0" class="stop-cielo-alto" />
              <stop offset="1" class="stop-cielo-basso" />
            </linearGradient>
            <linearGradient id="grad-acciaio" x1="0" y1="0" x2="1" y2="0">
              <stop offset="0" class="stop-acciaio-scuro" />
              <stop offset="0.45" class="stop-acciaio-chiaro" />
              <stop offset="1" class="stop-acciaio" />
            </linearGradient>
            <linearGradient id="grad-legno" x1="0" y1="0" x2="1" y2="0">
              <stop offset="0" class="stop-legno-chiaro" />
              <stop offset="1" class="stop-legno" />
            </linearGradient>
            <radialGradient id="grad-argento" cx="0.38" cy="0.34" r="0.75">
              <stop offset="0" class="stop-argento-chiaro" />
              <stop offset="0.6" class="stop-argento" />
              <stop offset="1" class="stop-argento-scuro" />
            </radialGradient>
            <linearGradient id="grad-selce" x1="0" y1="0" x2="1" y2="1">
              <stop offset="0" class="stop-selce-chiara" />
              <stop offset="0.55" class="stop-selce" />
              <stop offset="1" class="stop-selce-scura" />
            </linearGradient>
            <radialGradient id="grad-conchiglia" cx="0.42" cy="0.4" r="0.7">
              <stop offset="0" class="stop-conchiglia" />
              <stop offset="1" class="stop-conchiglia-scura" />
            </radialGradient>
            <linearGradient id="grad-vaso" x1="0" y1="0" x2="1" y2="0">
              <stop offset="0" class="stop-terracotta-chiara" />
              <stop offset="0.55" class="stop-terracotta" />
              <stop offset="1" class="stop-terracotta-scura" />
            </linearGradient>
            <linearGradient id="grad-luce" x1="0" y1="0" x2="1" y2="0">
              <stop offset="0" stop-color="#fff" stop-opacity="0" />
              <stop offset="0.5" stop-color="#fff" stop-opacity="0.85" />
              <stop offset="1" stop-color="#fff" stop-opacity="0" />
            </linearGradient>

            <clipPath id="clip-moneta"><circle r="58" /></clipPath>
            <clipPath id="clip-punta"><path d="M0 -85C22 -50 38 -6 33 28L18 55L25 78L10 75L0 60L-10 75L-25 78L-18 55L-33 28C-38 -6 -22 -50 0 -85Z" /></clipPath>
            <clipPath id="vaso-sagoma"><path d="M-30 -84H30L28 -72C70 -60 74 -12 64 22C54 56 32 80 0 84C-32 80 -54 56 -64 22C-74 -12 -70 -60 -28 -72Z" /></clipPath>
            <clipPath id="coccio-0"><polygon points="-110,-110 10,-110 -2,-62 -8,-40 -110,-30" /></clipPath>
            <clipPath id="coccio-1"><polygon points="10,-110 110,-110 110,-20 30,10 12,-18 -8,-40 -2,-62" /></clipPath>
            <clipPath id="coccio-2"><polygon points="-110,-30 -8,-40 12,-18 -35,25 -110,10" /></clipPath>
            <clipPath id="coccio-3"><polygon points="12,-18 30,10 -10,40 -35,25" /></clipPath>
            <clipPath id="coccio-4"><polygon points="110,-20 110,110 -10,110 5,62 -10,40 30,10" /></clipPath>
            <clipPath id="coccio-5"><polygon points="-110,10 -35,25 -10,40 5,62 -10,110 -110,110" /></clipPath>

            <!-- the jar, drawn once and cut into six pieces -->
            <g id="vaso-disegno">
              <path d="M-34 -76C-62 -76 -64 -48 -50 -40" class="vaso-ansa" />
              <path d="M34 -76C62 -76 64 -48 50 -40" class="vaso-ansa" />
              <path d="M-30 -84H30L28 -72C70 -60 74 -12 64 22C54 56 32 80 0 84C-32 80 -54 56 -64 22C-74 -12 -70 -60 -28 -72Z" fill="url(#grad-vaso)" />
              <g clip-path="url(#vaso-sagoma)">
                <rect x="-80" y="-52" width="160" height="9" class="vaso-fascia" />
                <path d="M-80 -24L-68 -38L-56 -24L-44 -38L-32 -24L-20 -38L-8 -24L4 -38L16 -24L28 -38L40 -24L52 -38L64 -24L76 -38" class="vaso-onda" />
                <rect x="-80" y="-14" width="160" height="4" class="vaso-fascia" />
                <rect x="-80" y="30" width="160" height="6" class="vaso-fascia" />
                <ellipse cx="44" cy="10" rx="30" ry="80" class="vaso-ombra" />
              </g>
              <rect x="-38" y="-96" width="76" height="13" rx="5" class="vaso-labbro" />
            </g>

            <!-- the textures of the five layers, filled in by the script -->
            <pattern id="trama-0" patternUnits="userSpaceOnUse" width="480" height="480" data-trama></pattern>
            <pattern id="trama-1" patternUnits="userSpaceOnUse" width="480" height="480" data-trama></pattern>
            <pattern id="trama-2" patternUnits="userSpaceOnUse" width="480" height="480" data-trama></pattern>
            <pattern id="trama-3" patternUnits="userSpaceOnUse" width="480" height="480" data-trama></pattern>
            <pattern id="trama-4" patternUnits="userSpaceOnUse" width="640" height="640" data-trama></pattern>
          </defs>

          <g data-cielo></g>
          <g data-strati></g>
          <g data-radici></g>
          <g data-erba></g>
          <g data-picchetti>
            <path d="M244 -2V-58M536 -2V-58" class="picchetto" />
            <path d="M244 -48Q390 -40 536 -48" class="spago" />
            <g class="cartello" data-cartello>
              <path d="M590 0V-92" class="picchetto" />
              <rect x="536" y="-150" width="108" height="62" rx="6" class="cartello__asse" />
              <text x="590" y="-124" class="cartello__titolo">TRENCH B</text>
              <text x="590" y="-106" class="cartello__sotto">Underfield Museum</text>
            </g>
          </g>
          <g data-cavita></g>

          <g data-reperti>
            <!-- topsoil: a silver penny -->
            <g data-posto>
              <g data-reperto>
                <g class="dentro" data-dentro>
                  <g data-faccia>
                    <circle r="58" fill="url(#grad-argento)" class="moneta" />
                    <circle r="49" class="moneta-giro" />
                    <g data-perline></g>
                    <path d="M0 -46V46M-46 0H46" class="moneta-croce" />
                    <g data-pallini-moneta></g>
                    <g clip-path="url(#clip-moneta)">
                      <g transform="rotate(22)"><rect x="-14" y="-90" width="26" height="180" fill="url(#grad-luce)" data-luccichio /></g>
                    </g>
                  </g>
                </g>
              </g>
            </g>
            <!-- loam: a storage jar in six pieces -->
            <g data-posto>
              <g data-reperto>
                <g class="dentro" data-dentro>
                  <g data-coccio><use href="#vaso-disegno" clip-path="url(#coccio-0)" /><polygon points="-110,-110 10,-110 -2,-62 -8,-40 -110,-30" class="crepa" clip-path="url(#vaso-sagoma)" /></g>
                  <g data-coccio><use href="#vaso-disegno" clip-path="url(#coccio-1)" /><polygon points="10,-110 110,-110 110,-20 30,10 12,-18 -8,-40 -2,-62" class="crepa" clip-path="url(#vaso-sagoma)" /></g>
                  <g data-coccio><use href="#vaso-disegno" clip-path="url(#coccio-2)" /><polygon points="-110,-30 -8,-40 12,-18 -35,25 -110,10" class="crepa" clip-path="url(#vaso-sagoma)" /></g>
                  <g data-coccio><use href="#vaso-disegno" clip-path="url(#coccio-3)" /><polygon points="12,-18 30,10 -10,40 -35,25" class="crepa" clip-path="url(#vaso-sagoma)" /></g>
                  <g data-coccio><use href="#vaso-disegno" clip-path="url(#coccio-4)" /><polygon points="110,-20 110,110 -10,110 5,62 -10,40 30,10" class="crepa" clip-path="url(#vaso-sagoma)" /></g>
                  <g data-coccio><use href="#vaso-disegno" clip-path="url(#coccio-5)" /><polygon points="-110,10 -35,25 -10,40 5,62 -10,110 -110,110" class="crepa" clip-path="url(#vaso-sagoma)" /></g>
                </g>
              </g>
            </g>
            <!-- clay: a flint arrowhead -->
            <g data-posto>
              <g data-reperto>
                <g class="dentro" data-dentro>
                  <path d="M0 -85C22 -50 38 -6 33 28L18 55L25 78L10 75L0 60L-10 75L-25 78L-18 55L-33 28C-38 -6 -22 -50 0 -85Z" fill="url(#grad-selce)" class="punta" />
                  <g class="scheggie">
                    <path d="M-30 22Q-14 10 -5 -12" pathLength="1" data-scheggia />
                    <path d="M-33 -4Q-16 -14 -7 -36" pathLength="1" data-scheggia />
                    <path d="M-22 -40Q-9 -47 -3 -66" pathLength="1" data-scheggia />
                    <path d="M30 24Q13 13 6 -8" pathLength="1" data-scheggia />
                    <path d="M33 -2Q17 -12 8 -34" pathLength="1" data-scheggia />
                    <path d="M22 -42Q9 -48 3 -66" pathLength="1" data-scheggia />
                    <path d="M0 -78V50" pathLength="1" class="cresta" data-scheggia />
                  </g>
                  <g clip-path="url(#clip-punta)">
                    <g transform="rotate(30)"><rect x="-16" y="-120" width="30" height="240" fill="url(#grad-luce)" data-luccichio /></g>
                  </g>
                </g>
              </g>
            </g>
            <!-- gravel: an ammonite, drawn by the script -->
            <g data-posto>
              <g data-reperto>
                <g class="dentro" data-dentro data-ammonite></g>
              </g>
            </g>
            <!-- bedrock: the bones of a dinosaur, drawn by the script -->
            <g data-posto>
              <g data-reperto>
                <g class="dentro" data-dentro data-scheletro></g>
              </g>
            </g>
          </g>

          <!-- the shovel: its tip is at 0 0 -->
          <g class="pala" data-pala transform="translate(400 -3000)">
            <path d="M-6 -470H6V-140H-6Z" fill="url(#grad-legno)" />
            <path d="M-6 -466L-24 -500Q0 -526 24 -500L6 -466" class="pala-impugnatura" />
            <path d="M-20 -504H20" class="pala-impugnatura" />
            <path d="M-11 -104L-7 -146H7L11 -104Z" class="pala-collo" />
            <path d="M0 4C-22 2 -36 -10 -38 -30L-38 -104Q0 -112 38 -104L38 -30C36 -10 22 2 0 4Z" fill="url(#grad-acciaio)" class="pala-lama" />
            <path d="M-26 -96Q0 -101 26 -96" class="pala-piega" />
          </g>
          <g data-zolle></g>
          <g data-polveri></g>
        </svg>

        <!-- the depth ruler on the side -->
        <div class="righello" aria-hidden="true">
          <svg class="righello__svg" data-righello preserveAspectRatio="xMinYMid slice"></svg>
          <svg class="lettura__punta" viewBox="0 0 12 16" data-lettura><path d="M0 0L12 8L0 16Z" /></svg>
          <div class="lettura" data-lettura>
            <div class="lettura__testo">
              <span class="lettura__metri" data-metri>0.00 m</span>
              <span class="lettura__strati">
                <span data-nome-strato>Ground level</span>
                <span data-nome-strato>Topsoil</span>
                <span data-nome-strato>Loam</span>
                <span data-nome-strato>Clay</span>
                <span data-nome-strato>Gravel</span>
                <span data-nome-strato>Bedrock</span>
              </span>
            </div>
          </div>
        </div>

        <!-- the museum labels, one for every find -->
        <div class="cartellini">
          <article class="cartellino" data-cartellino>
            <svg class="cartellino__filo" viewBox="0 0 80 34" aria-hidden="true"><path d="M8 34L40 4L72 34" /><circle cx="40" cy="4" r="3.5" /></svg>
            <div class="cartellino__carta" data-carta>
              <p class="cartellino__strato" data-riga>Topsoil, found at 0.3 m</p>
              <h3 class="cartellino__nome" data-riga>Silver penny</h3>
              <p class="cartellino__data" data-riga>Struck around 1270 AD</p>
              <p class="cartellino__testo" data-riga>Lost from a purse on the old market road. Small enough to vanish in one step, tough enough to wait seven centuries.</p>
              <p class="cartellino__dato" data-riga><span>In the ground</span><strong>about 750 years</strong></p>
            </div>
          </article>
          <article class="cartellino" data-cartellino>
            <svg class="cartellino__filo" viewBox="0 0 80 34" aria-hidden="true"><path d="M8 34L40 4L72 34" /><circle cx="40" cy="4" r="3.5" /></svg>
            <div class="cartellino__carta" data-carta>
              <p class="cartellino__strato" data-riga>Loam, found at 1.0 m</p>
              <h3 class="cartellino__nome" data-riga>Storage jar</h3>
              <p class="cartellino__data" data-riga>Roman, around 150 AD</p>
              <p class="cartellino__testo" data-riga>It came out of the ground in six pieces. Every one was there, so the jar went back together on site.</p>
              <p class="cartellino__dato" data-riga><span>In the ground</span><strong>about 1,870 years</strong></p>
            </div>
          </article>
          <article class="cartellino" data-cartellino>
            <svg class="cartellino__filo" viewBox="0 0 80 34" aria-hidden="true"><path d="M8 34L40 4L72 34" /><circle cx="40" cy="4" r="3.5" /></svg>
            <div class="cartellino__carta" data-carta>
              <p class="cartellino__strato" data-riga>Clay, found at 2.3 m</p>
              <h3 class="cartellino__nome" data-riga>Flint arrowhead</h3>
              <p class="cartellino__data" data-riga>Around 2500 BC</p>
              <p class="cartellino__testo" data-riga>Knapped from a single nodule of flint, one flake at a time. The edge can still cut a sheet of paper.</p>
              <p class="cartellino__dato" data-riga><span>In the ground</span><strong>about 4,500 years</strong></p>
            </div>
          </article>
          <article class="cartellino" data-cartellino>
            <svg class="cartellino__filo" viewBox="0 0 80 34" aria-hidden="true"><path d="M8 34L40 4L72 34" /><circle cx="40" cy="4" r="3.5" /></svg>
            <div class="cartellino__carta" data-carta>
              <p class="cartellino__strato" data-riga>Gravel, found at 4.5 m</p>
              <h3 class="cartellino__nome" data-riga>Ammonite</h3>
              <p class="cartellino__data" data-riga>Early Cretaceous</p>
              <p class="cartellino__testo" data-riga>The coiled shell of a sea creature, washed into an old river bed long after the sea had gone.</p>
              <p class="cartellino__dato" data-riga><span>Age</span><strong>about 130 million years</strong></p>
            </div>
          </article>
          <article class="cartellino" data-cartellino>
            <svg class="cartellino__filo" viewBox="0 0 80 34" aria-hidden="true"><path d="M8 34L40 4L72 34" /><circle cx="40" cy="4" r="3.5" /></svg>
            <div class="cartellino__carta" data-carta>
              <p class="cartellino__strato" data-riga>Bedrock, found at 8.4 m</p>
              <h3 class="cartellino__nome" data-riga>The Underfield <span class="intero">plant-eater</span></h3>
              <p class="cartellino__data" data-riga>Late Jurassic</p>
              <p class="cartellino__testo" data-riga>As long as a bus and gentle as a cow. The bones lay close together, so the skeleton could stand again.</p>
              <p class="cartellino__dato" data-riga><span>Age</span><strong>about 150 million years</strong></p>
            </div>
          </article>
        </div>
      </div>
    </section>

    <footer class="fine" id="fine">
      <p class="fine__etichetta" data-fine>You have reached bedrock</p>
      <p class="fine__frase" data-fine>Come and dig <em>the real thing.</em></p>
      <a class="fine__bottone" href="#scavo" data-fine><span>Book a dig day</span></a>
    </footer>
  </main>

  <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.

89 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 dig on scroll” from Animorio and fit it into my site

What it does

The page of a made-up museum, the Underfield Museum, and its «Gallery of the Ground». At the top the title «Twelve metres of buried time.» rises line by line. Below, the stage stops and shows the ground from the side: the sky with two slow clouds, the grass swaying, two pegs with a string and a «Trench B» sign. As you scroll the earth moves up and we go down: the roots grow in the first layer, and at every find cracks mark out a patch of soil, then a shovel comes down from above. Every shovelful is a small story: the blade goes in, the earth shakes and puffs a little dust, the shovel levers, lifts with the clods on it and flings them away in an arc that spins them and drops them off screen. When the hole is empty the shovel goes back up and the find comes out in its own way: in the topsoil a silver penny hops, flips twice and catches the light; in the loam six sherds lift and come back together into a jar that settles like a spring; in the clay a flint point straightens up and shows its flake scars; in the gravel an ammonite draws its coil from the outside in, rib after rib, and rolls into place; in the rock forty-seven bones fly to their places from the feet to the head, and at the end the jaw snaps. Next to every find a museum label swings in on its string, with the layer, the depth, the name, the date and how long it has been underground. On the left a depth ruler moves with the ground, with a pointer that reads the metres and the name of the layer. The pointer on a find makes it wobble (the coin flips, the dinosaur opens its mouth), and on the label it makes it sway. Scroll back and the clods go back into the hole and the ground closes up.

How it works

A world and a camera

The section is SCROLL_LENGTH screens tall and holds a sticky stage 100lvh tall with a single SVG. The ground is drawn in fixed coordinates (the grass at y = 0, the rock below 2760) and the camera is the viewBox: it is rewritten every frame with its y. The viewBox width follows the shape of the screen but always shows at least 520 free units, so on a narrow phone the dinosaur’s hole fits. The ruler is a second SVG with the same y and scale, so the ticks move with the earth; the depth goes through a piecewise metres-to-units table, because the rock is much thicker than the grass.

Layers, textures and roots

Each layer is a path between two wavy lines made of sines, filled twice: with its colour and with a pattern (crumbs, small stones, clay lines, pebbles, cracks and veins). The pattern shapes are picked by a seeded random generator, so the ground is always the same, and the ones crossing the tile’s edge are copied on the other side, so the tiles join with no cuts. The roots are paths with pathLength=1 that grow with stroke-dashoffset during the first descent.

The hole, cut into clods

Over every find there is an ellipse cut into CLODS pieces: an outer ring of quadrilaterals (the edge has three points per side, nudged at random, to make it rough) and an inner fan around a centre. The pieces fit exactly, and the same outline, darker, draws the hole underneath. Every clod has the colour and the pattern of its layer, so before the dig you can’t see it; then the edges show, like loosened earth. The clods are sorted from top to bottom and split into SCOOPS shovelfuls.

One paused timeline

Everything sits in a single paused timeline that a scrubbed ScrollTrigger moves back and forth. The camera and the shovel are objects of numbers (y, x, tilt) that onUpdate writes into attributes; the clods are moved by GSAP. Every shovelful: the approach, the blade going in with power3.in, three little knocks to the clods and the dust, the lever, the lift with the clods gathering on the blade, then the flick: x with power1.out and y in two parts (up with power2.out, down with power2.in), so a real arc, with the spin. Scroll back and everything goes back into place on its own.

The finds and the labels

Every find has its own entrance in the timeline: the coin turns with scaleX keyframes (1, -1, 1, -1, 1) and a glint cut by a clipPath; the jar is a single drawing in a <use> repeated six times, each with the clipPath of a sherd, and the sherds go back to 0 with back.out; the ammonite’s coil and ribs draw themselves with pathLength=1; the bones (built from segments, vertebrae along quadratic curves and ribs) start from random spots and come back with back.out, one after the other. Every find has an inner group just for the pointer, so its wobble never touches the timeline. The label is HTML: it comes in with elastic.out, turning around its nail, and its lines follow.

Values to change

NameFileDefaultWhat it changes
SCROLL_LENGTHscript.js9How many screens of scrolling the whole dig takes: more is slower.
SCOOPSscript.js3How many shovelfuls it takes to uncover each find.
CLODSscript.js12How many clods the earth over each find breaks into (the dinosaur’s, being bigger, has more).
FLINGscript.js1How far the shovel throws the earth.
WOBBLEscript.js1How much a find and its label wobble under the pointer: 0 keeps them still.
GRASS_SWAYscript.js1How much the grass moves in the wind: 0 keeps it still.
--strato-2style.css#a9623cThe colour of the clay; next to it are those of the other layers, the holes, the sky and the finds.

Try them in the Playground

When to use it

For a museum, an exhibition, an archaeology or geology site, a dinosaur park, a page for schools; but also for anyone telling something in layers to uncover on the way down: a company’s story from today back to its roots, a product taken apart piece by piece, a wine from the soil to the bottle.

On phones

The same animation with the sizes adapted: the ruler is a narrower strip with just the numbers, the metre reading sits at the top left, the hole is centred in the space left and the label sits at the bottom, almost as wide as the screen. A tap on a find makes it wobble.

With reduced motion

No shovel, no flying clods, no camera going down and no smooth scrolling: at every fifth of the section the ground fades out and comes back already at the right layer, with the hole open, the find in place and its label. The grass and the clouds stay still, the title fades in.

Pitfalls

  • With small pattern tiles (240 units) the bigger stones repeated in straight rows, and the ground looked like wallpaper. The tiles are 480 (640 for the rock), with more and smaller shapes, and nothing that stands out.
  • The clods only had the layer’s colour: in the gravel the earth to dig was a smooth patch among the pebbles. Every clod also has the layer’s pattern: the pattern is in userSpaceOnUse, so it follows the clod when it flies, and before the dig the clod can’t be told apart from the ground.
  • getBBox on a vertebra that has its own transform gives the size without that transform, so the bones started from the wrong places. Each vertebra is a group with no transform holding a rotated one: the outer group’s getBBox is the real one, and transformOrigin at 50% spins the bone around itself.
  • With the metre reading next to the ruler, on a phone the box covered the dinosaur’s head. On a phone the box moves to the top left, the pointer stays on the ruler, and the hole is centred in the part of the screen the ruler leaves free.
  • The layer’s name left and the new one came in 0.3 seconds later: halfway down the box had no name. The two moves now overlap.

Libraries

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

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

Testing

Tested on 11 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