
La carta olografica
Card, 3D, Hover
Gratis
Il piè di pagina di una piccola casa del tè, tutto fatto di un giardino di sabbia rastrellata illuminato da un sole basso, con le pietre, il muschio e gli anelli intorno, e il nome della casa impresso nella sabbia lungo il fondo. Il puntatore è un rastrello che scava solchi dove passa, un link puntato si prende un anello rastrellato intorno alla sua parola, e l'iscrizione alle lettere fa passare un rastrello largo che lascia il giardino come nuovo.
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>The zen garden footer</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/opsz.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/opsz-italic.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the footer of a small tea house: its whole ground is a raked sand garden lit by a low sun, with stones and
moss and rings raked round them, and the house's name pressed into the sand along the bottom. The pointer is
a rake that carves grooves where it goes, a link pointed at gets a ring raked round its word, and a sign-up
to the letters brings a wide rake across that leaves the garden as new -->
<footer class="zg" data-footer data-autoclic>
<canvas class="zg__sand" aria-hidden="true" data-sand></canvas>
<canvas class="zg__still" aria-hidden="true" data-still></canvas>
<canvas class="zg__rake" aria-hidden="true" data-rake></canvas>
<div class="zg__top">
<form class="zg__form" action="#" novalidate aria-labelledby="zg-news" data-form>
<h2 class="zg__title" id="zg-news" data-in>Letters from the tea house</h2>
<p class="zg__lede" data-in>New harvests, tasting evenings and the garden through the year. One letter each season.</p>
<label class="sr" for="zg-email">Email address</label>
<div class="zg__field" data-field data-in>
<input class="zg__input" id="zg-email" name="email" type="email" inputmode="email" autocomplete="email" autocapitalize="off" spellcheck="false" enterkeyhint="send" placeholder="you@example.com" aria-describedby="zg-note" aria-invalid="false" data-input>
<button class="zg__send" type="submit" data-send>
<span class="zg__send-bg"></span>
<span class="zg__send-label" data-send-label>Subscribe</span>
<svg class="zg__spin" viewBox="0 0 24 24" aria-hidden="true" data-spin><circle cx="12" cy="12" r="8"/></svg>
<svg class="zg__done" viewBox="0 0 24 24" aria-hidden="true" data-done><path d="M6.4 12.6l3.7 3.7 7.6-8.6"/></svg>
</button>
</div>
<p class="zg__note" id="zg-note" aria-live="polite" data-note data-in><span class="zg__line">Four letters a year. Leave with one click.</span></p>
</form>
<!-- where the stones lie: the script reads these boxes, the stones are drawn in the sand -->
<div class="zg__garden" aria-hidden="true">
<span class="zg__stone zg__stone--big" data-stone></span>
<span class="zg__stone zg__stone--small" data-stone></span>
</div>
<nav class="zg__cols" aria-label="Footer">
<div class="zg__col" data-in>
<h3 class="zg__head">Visit</h3>
<ul>
<li><a class="zg__link" href="#" data-link>Opening hours</a></li>
<li><a class="zg__link" href="#" data-link>Find us</a></li>
<li><a class="zg__link" href="#" data-link>Private rooms</a></li>
<li><a class="zg__link" href="#" data-link>Gift cards</a></li>
</ul>
</div>
<div class="zg__col" data-in>
<h3 class="zg__head">Tea</h3>
<ul>
<li><a class="zg__link" href="#" data-link>Our teas</a></li>
<li><a class="zg__link" href="#" data-link>Tastings</a></li>
<li><a class="zg__link" href="#" data-link>Tea ware</a></li>
<li><a class="zg__link" href="#" data-link>Wholesale</a></li>
</ul>
</div>
<div class="zg__col" data-in>
<h3 class="zg__head">House</h3>
<ul>
<li><a class="zg__link" href="#" data-link>Our story</a></li>
<li><a class="zg__link" href="#" data-link>The garden</a></li>
<li><a class="zg__link" href="#" data-link>Journal</a></li>
<li><a class="zg__link" href="#" data-link>Contact</a></li>
</ul>
</div>
</nav>
</div>
<div class="zg__base" data-in>
<p class="zg__brand">
<svg class="zg__mark" viewBox="0 0 24 24" aria-hidden="true"><path d="M12 22V3.2"/><path d="M12 6.4L8.6 9.6M12 6.4l3.4 3.2"/><path d="M12 10.6l-5 4.4M12 10.6l5 4.4"/><path d="M12 15l-6.6 5.2M12 15l6.6 5.2"/></svg>
<span class="zg__copy"><svg viewBox="0 0 12 12" aria-hidden="true"><circle cx="6" cy="6" r="5.1"/><path d="M7.9 4.5a2.3 2.3 0 1 0 0 3"/></svg><span class="sr">Copyright</span> 2026 Hollow Pine Tea House</span>
<span class="zg__hours">Open Wednesday to Sunday, 10 till 6</span>
</p>
<nav class="zg__legal" aria-label="Legal">
<a class="zg__link zg__link--small" href="#" data-link>Privacy</a>
<a class="zg__link zg__link--small" href="#" data-link>Terms</a>
<a class="zg__link zg__link--small" href="#" data-link>Cookies</a>
</nav>
</div>
<!-- the house's name: real text, pressed into the sand by the script where the text stands -->
<div class="zg__foot">
<p class="zg__name" data-name><span data-word>Hollow</span> <span data-word>Pine</span></p>
<span class="zg__stone zg__stone--corner" aria-hidden="true" data-stone></span>
</div>
</footer>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.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.
61 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 «Il piè di pagina col giardino zen» da Animorio e adattala al mio sitoLa sabbia è un'altezza ogni CELL pixel, disegnata su un canvas di quella misura che il browser allarga sfumando. Per ogni punto la pendenza viene dalle differenze coi vicini, e un sole basso (SUN e SUN_HEIGHT) la illumina alla Lambert: la luce che prende, divisa per quella del terreno piatto, sceglie fra tre colori della sabbia (piatta, al sole, in ombra), una cavità prende un po' d'ombra (il laplaciano) e la luce si scalda appena dalla parte del sole. La grana è un rumore nell'altezza di ogni punto più una polvere fine di granelli chiari e scuri disegnata una volta sola ai pixel dello schermo.
Si calcola una volta: righe dritte con un'onda lenta e una profondità che varia appena, come rastrellate a mano; anelli intorno alle pietre misurati dal bordo del muschio lungo il raggio che parte dal centro della pietra, più tondi man mano che si allontanano, con le righe che finiscono sulla cresta più esterna. Il nome si disegna col suo carattere su un canvas nascosto, grande il doppio, proprio dove stanno le parole vere (il riquadro di ogni parola più fontBoundingBoxAscent); la sfocatura ne fa le pareti dello stampo, il fondo è piatto e un po' più scuro, intorno la sabbia è lisciata e sollevata.
La testa del rastrello si muove solo quando il puntatore è più lontano di HANDLE pixel, e allora dritta verso di lui: così resta indietro e gira per seguirlo, e i denti stanno sempre di traverso. Fra due posizioni del puntatore si va a passi di 0,7 punti, così un gesto veloce non salta niente. A ogni passo la sabbia dentro la larghezza del rastrello prende il profilo dei denti (un coseno con le conche tonde e le creste più strette), i denti esterni ammucchiano una cresta e appena fuori la sabbia spinta via sale; dove ci sono pietre e muschio non si scava. Si illumina di nuovo solo il rettangolo toccato, col rettangolo sporco di putImageData.
Un anello non si scrive nella sabbia: mentre la si illumina, il suo nastro (due denti) prende il posto della sabbia sotto, fin dove GSAP l'ha già tracciato (l'angolo contato dall'estremo sinistro, con la punta morbida), e dentro l'ovale la sabbia si liscia. La distanza dall'ovale viene dall'equazione dell'ellisse divisa per la sua pendenza. Andandosene la sua forza scende a zero e sotto ricompare la sabbia com'era, solchi compresi.
Dopo l'iscrizione un tween di GSAP porta il fronte da sinistra a destra in SWEEP secondi: ogni colonna che passa riprende la sabbia appena rastrellata, e davanti alla barra si gonfia un mucchietto di sabbia spinta. La barra coi denti e il rastrello piccolo si disegnano su un terzo canvas, con l'ombra. Pietre, muschio e ombre si disegnano una volta, pixel per pixel, alla risoluzione dello schermo: un masso piatto in cima e tondo alle spalle, crepe da un rumore a creste, la grana del granito, un velo di lucido, un cuscino di muschio fatto di cupolette e il muschio che sale dal lato in ombra; l'ombra portata è la sagoma disegnata fuori dal canvas con la sua ombra sfocata riportata dentro.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
TINES | script.js | 5 | Quanti denti ha il rastrello: tanti solchi lascia a ogni passata. |
TINE_GAP | script.js | 9 | Quanto sono distanti i denti, in pixel: un solco e una cresta. Vale anche per le righe e gli anelli del giardino. |
DEPTH | script.js | 1.2 | Quanto scavano i denti, in pixel di sabbia: di più fa solchi più netti, con più luce e più ombra. |
PRESS | script.js | 2.6 | Quanto è impresso nella sabbia il nome lungo il fondo, in pixel: a 0 sparisce. |
SUN | script.js | 125 | Da dove arriva il sole, in gradi intorno al piè di pagina: 90 dall'alto, 180 da sinistra. Da sinistra pura le righe orizzontali quasi spariscono. |
SUN_HEIGHT | script.js | 24 | Quanto è alto il sole, in gradi: più basso fa i solchi più marcati e le ombre delle pietre più lunghe. |
GRAIN | script.js | 0.6 | Quanta grana ha la sabbia: a 0 è liscia come gesso. |
RINGS | script.js | 3 | Quanti anelli sono rastrellati intorno a ogni pietra. |
CELL | script.js | 2 | Quanti pixel copre ogni punto della sabbia: di più è meno lavoro e sabbia più morbida, di meno più dettaglio. |
HANDLE | script.js | 34 | Quanto resta indietro la testa del rastrello rispetto al puntatore, in pixel: di più fa curve più larghe e morbide. |
SWEEP | script.js | 1.9 | Quanto ci mette il rastrello largo ad attraversare il piè di pagina dopo un'iscrizione, in secondi. |
WAIT | script.js | 1.1 | Quanto dura l'iscrizione nella demo, in secondi. |
Per il piè di pagina di una casa del tè, di una spa, di un ritiro di meditazione, di un'app per la calma o il sonno, di un vivaio di bonsai, di un ceramista o di uno studio di architettura del paesaggio: ovunque il fondo della pagina possa essere un posto dove fermarsi un momento e giocare con la sabbia.
Il piè di pagina prende la larghezza dello schermo e diventa una colonna più alta: la newsletter, poi una striscia di sabbia libera con le due pietre e i loro anelli, poi le tre colonne di link, il marchio, l'orario e i link legali, e il nome impresso su due righe, Hollow e Pine, con la terza pietra accanto a Pine. La sabbia ha meno punti ma la stessa grana. Un dito trascinato di lato rastrella (su e giù scorre la pagina), e il rastrello si vede finché il dito è giù; toccando un link l'anello si traccia intorno alla parola e resta un momento.
Niente passa da solo: il giardino è già rastrellato quando il piè di pagina compare, in dissolvenza. Il rastrello resta, perché lo muove la mano. Un link puntato ha il suo anello già chiuso, che compare in dissolvenza insieme alla pozza liscia; il campo sbagliato non trema, il pulsante non si stringe e l'arco sta fermo; all'iscrizione il rastrello largo non passa e il giardino torna come nuovo in dissolvenza, dove si trova.
GSAP 3.15.0, Newsreader (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 23 KB; le librerie: GSAP 28 KB.
Provata il 7 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.