
Parole che si fondono
Testo, Scroll, SVG
NuovaGratis
Scorri dentro l’anteprima
La sezione di un terreno vista di lato: scendendo si attraversano erba e radici, terra, argilla, ghiaia e roccia. In ogni strato una pala scava, lancia via la terra a palate, e dalla buca esce un reperto: una moneta che si gira, un vaso che si ricompone, una punta di freccia, un’ammonite che disegna la sua spirale e uno scheletro di dinosauro che si monta osso per osso. Accanto arriva il cartellino del museo, e un righello a lato segna la profondità.
Una cartella che funziona da sola: index.html, style.css, script.js e le librerie da CDN. Nelle schede React e Vue la stessa demo è già un componente, che spegne le sue animazioni quando esce dalla pagina.
<!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>Cambia valori, colori e testi con le manopole e guarda l’animazione rispondere dal vivo. Oppure scrivi tu nel codice. Poi scarica la cartella con le tue modifiche.
89 valori da cambiare
Col connettore di Animorio, Claude Code la prende da qui con tutta la sua guida e la adatta al tuo progetto. Incolla questa richiesta:
Prendi «Lo scavo allo scroll» da Animorio e adattala al mio sitoLa sezione è alta SCROLL_LENGTH schermi e dentro c’è un palco sticky alto 100lvh con un solo SVG. Il terreno è disegnato in coordinate fisse (l’erba a y = 0, la roccia sotto i 2760) e la telecamera è il viewBox: a ogni fotogramma si riscrive con la sua y. La larghezza del viewBox segue la forma dello schermo, ma ne mostra sempre almeno 520 unità libere, così su un telefono stretto la buca del dinosauro ci sta. Il righello è un secondo SVG con la stessa y e la stessa scala, quindi le tacche scorrono insieme alla terra; la profondità passa per una tabella metri-unità a tratti, perché la roccia è molto più spessa dell’erba.
Ogni strato è un tracciato fra due linee ondulate fatte di seni, riempito due volte: col suo colore e con un pattern (briciole, sassolini, linee d’argilla, ciottoli, crepe e vene). Le forme dei pattern sono scelte da un generatore casuale con un seme, così il terreno è sempre lo stesso, e quelle che passano sul bordo della piastrella vengono copiate dall’altra parte, perché le piastrelle si uniscano senza tagli. Le radici sono tracciati con pathLength=1 che crescono con stroke-dashoffset durante la prima discesa.
Sopra ogni reperto c’è un’ellisse tagliata in CLODS pezzi: un anello esterno di quadrilateri (il bordo ha tre punti per lato, spostati un po’ a caso, per farlo irregolare) e un ventaglio interno attorno a un centro. I pezzi combaciano esattamente, e lo stesso contorno, più scuro, disegna la buca sotto. Ogni zolla ha il colore e il pattern del suo strato, quindi prima dello scavo non si vede; poi i bordi diventano visibili, come terra smossa. Le zolle sono ordinate dall’alto in basso e divise in SCOOPS palate.
Tutto sta in una sola timeline in pausa, che uno ScrollTrigger in scrub porta avanti e indietro. La telecamera e la pala sono oggetti di numeri (y, x, inclinazione) che onUpdate scrive negli attributi; le zolle sono mosse da GSAP. Ogni palata: avvicinamento, la lama che entra con power3.in, tre colpetti alle zolle e la polvere, la leva, la salita con le zolle che si raccolgono sulla lama, poi lo scatto: x con power1.out e y in due tempi (su con power2.out, giù con power2.in), quindi un arco vero, con la rotazione. Scorrendo indietro tutto torna al suo posto da solo.
Ogni reperto ha la sua uscita nella timeline: la moneta gira con dei keyframes di scaleX (1, -1, 1, -1, 1) e un riflesso tagliato da un clipPath; il vaso è un solo disegno in un <use> ripetuto sei volte, ognuno col clipPath di un coccio, e i cocci tornano a 0 con back.out; la spirale e le coste dell’ammonite si disegnano con pathLength=1; le ossa (generate da segmenti, vertebre lungo curve quadratiche e coste) partono da posti a caso e tornano con back.out, una dopo l’altra. Ogni reperto ha un gruppo interno solo per il puntatore, così il suo dondolio non tocca la timeline. Il cartellino è HTML: entra con elastic.out ruotando attorno al chiodo, e le righe lo seguono.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
SCROLL_LENGTH | script.js | 9 | Quanti schermi di scorrimento dura tutto lo scavo: di più è più lento. |
SCOOPS | script.js | 3 | Quante palate servono per scoprire ogni reperto. |
CLODS | script.js | 12 | In quante zolle si rompe la terra sopra ogni reperto (quella del dinosauro, più grande, ne ha di più). |
FLING | script.js | 1 | Quanto lontano la pala lancia la terra. |
WOBBLE | script.js | 1 | Quanto dondolano un reperto e il suo cartellino sotto il puntatore: 0 fermi. |
GRASS_SWAY | script.js | 1 | Quanto si muove l’erba al vento: 0 ferma. |
--strato-2 | style.css | #a9623c | Il colore dell’argilla; accanto ci sono quelli degli altri strati, delle buche, del cielo e dei reperti. |
Per un museo, una mostra, un sito di archeologia o di geologia, un parco dei dinosauri, una pagina per le scuole; ma anche per chi racconta qualcosa a strati da scoprire scendendo: la storia di un’azienda dal presente alle origini, un prodotto smontato pezzo per pezzo, un vino dal terreno alla bottiglia.
La stessa animazione con le misure adattate: il righello è una striscia più stretta con i soli numeri, la lettura dei metri sta in alto a sinistra, la buca è centrata nello spazio che resta e il cartellino sta in basso, largo quasi come lo schermo. Un tocco su un reperto lo fa dondolare.
Niente pala, niente zolle che volano, niente telecamera che scende né scorrimento morbido: a ogni quinto della sezione il terreno sparisce in dissolvenza e torna già allo strato giusto, con la buca aperta, il reperto al suo posto e il cartellino. L’erba e le nuvole stanno ferme, il titolo compare in dissolvenza.
GSAP 3.15.0, Lenis 1.3.26, Fraunces (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 20 KB; le librerie: GSAP + ScrollTrigger 45 KB, Lenis 5,3 KB.
Provata il 11 ottobre 2026
Puoi usarla nei tuoi progetti e in quelli dei tuoi clienti. Non puoi rivenderla né ridistribuirla così com’è. GSAP resta sotto la sua licenza Standard. Licenza completa.
Con l’email e la password del tuo account.
oppure con l’email
Hai fatto l’accesso come .
Con l’account scarichi lo zip di ogni animazione e di ogni pacchetto, gratis.