
La valutazione a stelle
Valutazioni, SVG, Hover
NuovaGratis
Nello stile ricco, colorato e pieno di cose: il modulo contatti di una locanda sul mare, The Driftwood Inn. A sinistra un angolo di spiaggia al tramonto, col sole che scende, le onde, una barca a vela all’orizzonte e la riva che va e viene; sulla sabbia una bottiglia vuota, il suo tappo di sughero, un rotolo di spago e un foglio a righe. Mentre scrivi la lettera si riempie d’inchiostro: le parole del messaggio diventano righe di calligrafia col pennino che corre in fondo, l’email diventa il mittente col timbro del dollaro della sabbia, il nome la firma con lo svolazzo. Inviato, il foglio si arrotola, si lega con lo spago e scivola nella bottiglia, il tappo vola nel collo, la bottiglia si rovescia, un’onda risale la spiaggia, la prende e la porta al largo, verso il sole, finché diventa un riflesso.
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 message in a bottle contact form</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/index.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 class="stage">
<!-- the contact form of a seaside inn: beside it a corner of the beach at sunset, with an empty bottle standing in
the sand, its cork and a sheet of paper. While you write, the letter fills with ink: the message line by line
with a nib running at the end, the email as the return address with a sand dollar stamp, the name as the
signature. Sent, the letter rolls up, is tied with twine and slides into the bottle, the cork flies in, the
bottle tips over, rolls to the water and drifts away on the waves to the sun -->
<section class="mare" aria-labelledby="mare-title" data-mare data-autoclic>
<div class="mare__scene" aria-hidden="true">
<svg class="scene" viewBox="0 0 300 360" data-svg>
<defs>
<linearGradient id="mare-sky" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="stop-sky-top"/>
<stop offset="1" class="stop-sky"/>
</linearGradient>
<linearGradient id="mare-sea" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="stop-sea-far"/>
<stop offset="1" class="stop-sea"/>
</linearGradient>
<linearGradient id="mare-sand" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="stop-sand-wet"/>
<stop offset="0.16" class="stop-sand"/>
<stop offset="1" class="stop-sand-low"/>
</linearGradient>
<linearGradient id="mare-glass" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" class="stop-glass-dark"/>
<stop offset="0.3" class="stop-glass-light"/>
<stop offset="0.55" class="stop-glass"/>
<stop offset="1" class="stop-glass-dark"/>
</linearGradient>
<radialGradient id="mare-sun" cx="0.5" cy="0.5" r="0.5">
<stop offset="0" class="stop-sun"/>
<stop offset="0.45" class="stop-sun"/>
<stop offset="1" class="stop-sun-glow"/>
</radialGradient>
<linearGradient id="mare-wood" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" class="stop-wood-light"/>
<stop offset="1" class="stop-wood"/>
</linearGradient>
<clipPath id="mare-room">
<rect x="0" y="0" width="300" height="360" rx="18"/>
</clipPath>
<clipPath id="mare-above">
<rect x="0" y="0" width="300" height="170"/>
</clipPath>
</defs>
<g clip-path="url(#mare-room)">
<!-- the sky at sunset, two clouds drifting -->
<rect x="0" y="0" width="300" height="172" fill="url(#mare-sky)"/>
<g class="clouds" data-clouds>
<g data-cloud="0" transform="translate(40 52)">
<path class="cloud" d="M0 14 C 0 6, 9 2, 16 6 C 20 -2, 34 -3, 39 5 C 46 2, 56 7, 54 14 Z"/>
<path class="cloud__light" d="M8 10 C 14 7, 20 7, 26 9"/>
</g>
<g data-cloud="1" transform="translate(196 34)">
<path class="cloud" d="M0 11 C 1 5, 8 2, 13 5 C 17 -1, 28 -1, 31 5 C 37 3, 44 7, 42 11 Z"/>
</g>
</g>
<!-- the sun going down behind the horizon -->
<g clip-path="url(#mare-above)">
<circle cx="220" cy="160" r="46" fill="url(#mare-sun)" class="sun__glow"/>
<circle cx="220" cy="160" r="20" class="sun"/>
</g>
<!-- the sea: a band that darkens towards the beach, a sailing boat on the horizon, the glints under the sun -->
<rect x="0" y="168" width="300" height="96" fill="url(#mare-sea)"/>
<path d="M0 168.5 H300" class="horizon"/>
<g class="boat" data-boat transform="translate(56 166)">
<path d="M-7 0 H7 L5 2.6 H-5 Z" class="boat__hull"/>
<path d="M0 -0.6 V-15" class="boat__mast"/>
<path d="M0.8 -14 L8 -2 H0.8 Z" class="boat__sail"/>
<path d="M-0.8 -11 L-6 -2 H-0.8 Z" class="boat__jib"/>
</g>
<g class="glints" data-glints></g>
<g class="waves" data-waves></g>
<!-- the bottle out at sea, drawn again small while it drifts -->
<g data-floater opacity="0">
<g data-floater-tilt>
<path class="bottle__body" d="M-22 -9 C -22 -12, -19 -13, -16 -13 H6 C 10 -13, 12 -10, 14 -6 H22 V6 H14 C 12 10, 10 13, 6 13 H-16 C -19 13, -22 12, -22 9 Z"/>
<rect x="22" y="-4.5" width="7" height="9" rx="2" class="cork"/>
<rect x="-16" y="-4" width="26" height="8" rx="4" class="roll__paper"/>
<path d="M-18 -9 H8" class="bottle__shine"/>
</g>
<path d="M-26 14 C -16 10, 16 10, 28 14" class="floater__ripple"/>
</g>
<!-- the beach: the water's edge that washes up and back, wet sand, then the dry sand -->
<rect x="0" y="240" width="300" height="120" fill="url(#mare-sand)"/>
<path class="wash" data-wash d="M0 248 C 60 252, 120 246, 180 250 C 230 253, 270 247, 300 250 V 236 H 0 Z"/>
<path class="foam" data-foam d="M0 248 C 60 252, 120 246, 180 250 C 230 253, 270 247, 300 250"/>
<g class="grains" data-grains></g>
<!-- things on the sand: a piece of driftwood, two shells, pebbles, a coil of twine -->
<g class="drift" transform="translate(196 342) rotate(-6)">
<path d="M-70 -7 C -50 -12, 10 -11, 52 -8 C 60 -7, 64 -3, 62 2 C 40 6, -30 7, -66 5 C -74 4, -76 -4, -70 -7 Z" fill="url(#mare-wood)"/>
<path d="M-60 -4 C -30 -6, 10 -6, 48 -4 M-50 1 C -20 0, 20 0, 44 2 M-8 -8 C -2 -6, 4 -6, 8 -8" class="drift__grain"/>
<ellipse cx="22" cy="-2" rx="4" ry="2.2" class="drift__knot"/>
</g>
<g class="shell" transform="translate(26 318) rotate(-14)">
<path d="M0 0 C -9 -2, -13 -11, -9 -17 C -5 -22, 5 -22, 9 -17 C 13 -11, 9 -2, 0 0 Z" class="shell__body"/>
<path d="M0 -1 L-7 -16 M0 -1 L-3 -19 M0 -1 L1 -20 M0 -1 L5 -18 M0 -1 L8 -14" class="shell__rib"/>
<path d="M-4 0 H4 L3 3 H-3 Z" class="shell__hinge"/>
</g>
<g class="shell shell--small" transform="translate(278 300) rotate(22) scale(0.7)">
<path d="M0 0 C -9 -2, -13 -11, -9 -17 C -5 -22, 5 -22, 9 -17 C 13 -11, 9 -2, 0 0 Z" class="shell__body"/>
<path d="M0 -1 L-7 -16 M0 -1 L-3 -19 M0 -1 L1 -20 M0 -1 L5 -18 M0 -1 L8 -14" class="shell__rib"/>
</g>
<ellipse cx="128" cy="344" rx="7" ry="4" class="pebble"/>
<ellipse cx="139" cy="347" rx="4" ry="2.6" class="pebble pebble--light"/>
<ellipse cx="56" cy="352" rx="5" ry="3" class="pebble pebble--light"/>
<!-- the bottle on the sand: shadow, the glass behind, the letter when it goes in, the glass in front -->
<g data-bottle-shadow>
<ellipse cx="78" cy="309" rx="22" ry="5" class="bottle__shadow"/>
</g>
<g data-bottle>
<g data-bottle-turn>
<path class="bottle__back" d="M64 308 C 60 308, 58 305, 58 301 V 256 C 58 246, 66 240, 72 236 V 222 H 84 V 236 C 90 240, 98 246, 98 256 V 301 C 98 305, 96 308, 92 308 Z"/>
<g data-inside></g>
<path class="bottle__body" d="M64 308 C 60 308, 58 305, 58 301 V 256 C 58 246, 66 240, 72 236 V 222 H 84 V 236 C 90 240, 98 246, 98 256 V 301 C 98 305, 96 308, 92 308 Z"/>
<path d="M71 222 H85 V 219 C 85 217.5, 84 217, 82.5 217 H 73.5 C 72 217, 71 217.5, 71 219 Z" class="bottle__lip"/>
<path d="M63 258 C 63 250, 67 246, 72 242" class="bottle__shine"/>
<path d="M63 266 V 298" class="bottle__shine"/>
<path d="M93 270 V 296" class="bottle__shine bottle__shine--thin"/>
<path d="M58 300 C 66 304, 90 304, 98 300" class="bottle__base"/>
<!-- a scrap of an old label -->
<path d="M64 270 L 92 268 L 91 284 L 66 285 Z" class="bottle__label"/>
<path d="M68 275 H 86 M 69 279 H 82" class="bottle__label-line"/>
<g data-cork-in opacity="0">
<path d="M72 223 C 72 213, 73 210, 74 209 H 82 C 83 210, 84 213, 84 223 Z" class="cork"/>
<path d="M74 213 H82 M73.5 217 H82.5" class="cork__dots"/>
</g>
</g>
</g>
<!-- the cork and the twine lying on the sand -->
<g data-cork transform="translate(118 312) rotate(70)">
<path d="M-5 -8 L 5 -8 L 6 8 L -6 8 Z" class="cork"/>
<ellipse cx="0" cy="-8" rx="5" ry="1.8" class="cork__top"/>
<circle cx="-1.5" cy="-2" r="0.7" class="cork__dot"/>
<circle cx="2" cy="2" r="0.6" class="cork__dot"/>
<circle cx="-2" cy="4.5" r="0.6" class="cork__dot"/>
</g>
<g class="twine" transform="translate(110 330)">
<ellipse cx="0" cy="0" rx="9" ry="3.4" class="twine__coil"/>
<ellipse cx="0" cy="-1.2" rx="6" ry="2.2" class="twine__coil"/>
<path d="M8 1 C 14 3, 18 1, 22 4" class="twine__end"/>
</g>
<!-- the letter on a flat stone: ruled paper, the return address, the stamp, the ink lines, the signature -->
<g data-letter-shadow>
<path d="M146 268 L 282 262 L 286 342 L 150 348 Z" class="letter__shadow"/>
</g>
<g data-letter transform="translate(214 302) rotate(-3)">
<g data-paper>
<path d="M-66 -40 L 66 -40 L 66 40 C 40 42, -40 42, -66 40 Z" class="paper"/>
<path d="M-66 -40 L 66 -40 L 66 -34 L -66 -34 Z" class="paper__top"/>
<g class="paper__rules">
<path d="M-58 -16 H58 M-58 -6 H58 M-58 4 H58 M-58 14 H58 M-58 24 H58"/>
</g>
<path d="M-52 -40 V 40" class="paper__margin"/>
<text x="-47" y="-25" class="paper__from" data-from></text>
<g data-stamp transform="translate(52 -24)" opacity="0">
<circle r="9" class="stamp"/>
<g class="stamp__petals">
<ellipse cx="0" cy="-4" rx="1.4" ry="3"/>
<ellipse cx="0" cy="-4" rx="1.4" ry="3" transform="rotate(72)"/>
<ellipse cx="0" cy="-4" rx="1.4" ry="3" transform="rotate(144)"/>
<ellipse cx="0" cy="-4" rx="1.4" ry="3" transform="rotate(216)"/>
<ellipse cx="0" cy="-4" rx="1.4" ry="3" transform="rotate(288)"/>
</g>
<circle r="11.5" class="stamp__ring"/>
</g>
<g data-lines></g>
<g data-blots></g>
<text x="56" y="35" class="paper__sign" text-anchor="end" data-sign></text>
<path d="M10 37 C 24 40, 40 38, 58 36" class="paper__flourish" data-flourish/>
<g data-nib opacity="0">
<path d="M0 0 L 4 -11 L 7 -10 Z" class="nib"/>
<path d="M4 -11 L 14 -34" class="nib__quill"/>
<path d="M14 -34 C 8 -30, 6 -22, 5 -14 M14 -34 C 18 -28, 16 -20, 8 -12" class="nib__vane"/>
</g>
</g>
<!-- the roll the letter becomes -->
<g data-roll opacity="0">
<rect x="-6" y="-40" width="12" height="80" rx="6" class="roll__paper"/>
<ellipse cx="0" cy="-40" rx="6" ry="2.4" class="roll__end"/>
<path d="M0 -40 m -3 0 a 3 1.2 0 1 0 6 0 a 1.6 0.6 0 1 0 -3 0" class="roll__spiral"/>
<g data-tie opacity="0">
<path d="M-6.4 -3 H6.4 M-6.4 1 H6.4" class="tie"/>
<path d="M5 -1 C 12 -6, 14 2, 18 -2 M5 -1 C 11 4, 14 8, 19 6" class="tie"/>
</g>
</g>
</g>
<rect x="0.5" y="0.5" width="299" height="359" rx="17.5" class="scene__edge"/>
</g>
</svg>
</div>
<div class="mare__side">
<form class="mare__form" novalidate data-form>
<p class="mare__kicker">The Driftwood Inn</p>
<h1 class="mare__title" id="mare-title">Write to us by sea</h1>
<div class="field" data-field="name">
<label class="field__label" for="mare-name">Your name</label>
<input class="field__input" id="mare-name" name="name" type="text" autocomplete="name" aria-describedby="mare-err-name" data-input>
<span class="field__err" id="mare-err-name" data-err></span>
</div>
<div class="field" data-field="email">
<label class="field__label" for="mare-email">Email</label>
<input class="field__input" id="mare-email" name="email" type="email" autocomplete="email" inputmode="email" aria-describedby="mare-err-email" data-input>
<span class="field__err" id="mare-err-email" data-err></span>
</div>
<div class="field" data-field="message">
<label class="field__label" for="mare-message">Message</label>
<textarea class="field__input" id="mare-message" name="message" rows="2" aria-describedby="mare-err-message" data-input></textarea>
<span class="field__err" id="mare-err-message" data-err></span>
</div>
<div class="mare__foot">
<button class="send" type="submit" data-send>
<svg class="send__wave" viewBox="0 0 22 14" aria-hidden="true">
<path d="M1 9 C 4 5, 7 5, 9 8 C 11 11, 14 11, 16 8 C 18 5, 20 5, 21 6"/>
<path d="M1 13 C 4 10, 7 10, 9 12 C 11 14, 14 14, 16 12" class="send__wave-low"/>
</svg>
<span class="send__word" data-word>Send by sea</span>
</button>
<span class="mare__note">We answer within a day.</span>
</div>
</form>
<!-- what stays once the bottle is at sea -->
<div class="done" data-done>
<p class="done__title">Your bottle is at sea</p>
<p class="done__text">It will reach the inn with the next tide. We write back to <span data-done-mail></span>.</p>
<button class="again" type="button" data-again>Write another</button>
</div>
</div>
<p class="sr" aria-live="polite" data-live></p>
</section>
</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.
37 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 modulo contatti del messaggio in bottiglia» da Animorio e adattala al mio sitoLa spiaggia è un SVG di 300 per 360: cielo, sole, mare e sabbia sono fissi, mentre le onde, i riflessi del sole e la riva si ridisegnano a ogni fotogramma dal ticker di GSAP con qualche seno.
Ogni parola del messaggio diventa un tratto di calligrafia: una curva a zig-zag con un ricciolo in su per le lettere alte (b, d, l, t…) e in giù per quelle basse (g, p, y…), che va a capo quando la riga è piena; il pennino si mette in fondo all’ultima parola.
Le parti che si muovono (lettera, rotolo, bottiglia, tappo, bottiglia al largo) hanno un oggetto di numeri ciascuna: GSAP li anima e il ticker li scrive nell’attributo transform, così ruotano attorno al punto giusto anche dentro gruppi già spostati.
Per arrotolarsi il foglio si stringe verso il bordo sinistro (scaleX attorno a quel bordo) mentre il rotolo corre da destra a sinistra; poi un rotolo gemello, disegnato dietro il vetro, scende nella bottiglia.
L’onda è la stessa riva che sale: un numero aggiunto all’altezza del bordo dell’acqua la fa risalire fino alla bottiglia e ritirarsi portandosela via.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
ROLL_TIME | script.js | 0.9 | Quanti secondi ci mette la lettera ad arrotolarsi. |
DRIFT_TIME | script.js | 4.2 | Quanti secondi ci mette la bottiglia ad arrivare al sole. |
WAVE_HEIGHT | script.js | 1 | Quanto sono alte le onde sul mare: 0 è la calma piatta. |
SURF | script.js | 3 | Di quanti pixel la riva va e viene sulla sabbia. |
INK_WIDTH | script.js | 2.5 | Quanto è larga una lettera della calligrafia sul foglio. |
WAIT | script.js | 0.4 | Quanti secondi dura l’invio finto prima che la lettera si arrotoli. |
TYPE_SPEED | script.js | 0.07 | Secondi per lettera quando l’anteprima scrive da sola. |
La pagina Contatti di un albergo o di una casa vacanze sul mare, di uno stabilimento balneare, di una scuola di vela, di un bar sulla spiaggia: dove scrivere deve sembrare un piccolo gesto da vacanza.
Sul telefono la spiaggia e il modulo restano affiancati, la spiaggia più stretta; gli errori vanno sotto il campo e la riga «We answer within a day» sparisce per fare posto.
Col movimento ridotto il mare sta fermo, l’inchiostro, il timbro e la firma compaiono senza molle; inviato, la lettera e la bottiglia sulla sabbia si dissolvono e la bottiglia compare già al largo.
GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0, Caveat (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 15 KB; le librerie: GSAP 28 KB.
Provata il 23 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.