
La barra laterale che si arriccia
Navigazione, SVG, Testo, Fisica, Transizioni
NuovaGratis
La chat di casa di tre coinquilini, dove il campo per scrivere è una pelle grigia fatta di punti su molle. Inviando, la pelle si stacca dal campo e si stringe intorno alle parole come una busta sottovuoto, diventa gialla e le porta su nella conversazione, allungandosi per strada e ondeggiando quando arriva; dal pulsante ne esce una nuova. La risposta si scrive in una bolla fantasma del colore di chi scrive: al posto delle parole crescono barrette lunghe come loro, a raffiche e con qualche ripensamento, e quando arriva la bolla si riempie e le barrette si sviluppano nelle parole.
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 vacuum-sealed chat</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/rubik@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the group chat of a shared flat: the field's grey skin closes round the words like a vacuum pack and carries
them up into the conversation, and a flatmate's answer is written in a ghost bubble that shows the shape of
its words before the words themselves -->
<section class="chat" aria-label="Flat 4B, group chat" data-chat data-autoclic>
<header class="chat__head">
<div class="chat__faces" aria-hidden="true">
<span class="face" style="--who: var(--who-1)">I</span>
<span class="face" style="--who: var(--who-2)">T</span>
</div>
<div class="chat__title">
<h2 class="chat__name">Flat 4B</h2>
<p class="chat__status" aria-hidden="true" data-status><span class="status__line">Iris, Theo and you</span></p>
</div>
</header>
<div class="chat__thread" data-thread>
<div class="chat__log" role="log" aria-live="polite" aria-label="Messages" data-log></div>
</div>
<form class="chat__composer" data-form>
<div class="field" data-field>
<label class="sr" for="chat-input">Message Flat 4B</label>
<textarea class="field__input" id="chat-input" rows="1" placeholder="Message Flat 4B" maxlength="280" enterkeyhint="send" aria-describedby="chat-keys" data-input></textarea>
<span class="sr" id="chat-keys">Enter sends, Shift and Enter starts a new line.</span>
<span class="field__caret" aria-hidden="true" data-caret></span>
<button class="send" type="submit" aria-label="Send" disabled data-send>
<span class="send__bg" aria-hidden="true"></span>
<svg class="send__arrow" viewBox="0 0 24 24" aria-hidden="true" data-arrow><path d="M12 18.6V5.8M6.6 11.2 12 5.8l5.4 5.4"/></svg>
</button>
</div>
</form>
<!-- the skins that move between the field and the conversation, and the words they carry -->
<svg class="chat__skins" aria-hidden="true" data-skins></svg>
<div class="chat__fly" aria-hidden="true" data-fly></div>
</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.
48 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 «La chat sottovuoto» da Animorio e adattala al mio sitoOgni forma che si muove è un anello di 62 punti messi sempre nello stesso ordine su un rettangolo arrotondato (sette su ogni angolo, dodici sui lati lunghi, cinque su quelli corti): così un angolo del campo diventa sempre un angolo della bolla. Ogni punto è tirato verso il suo posto da una molla smorzata, x'' = −k(x − meta) − c·x', a passi di 1/240 di secondo col passo del fotogramma limitato a 1/30; i due vicini lo trascinano, ma sulla differenza dal proprio posto e non sulla posizione, così la pelle si posa esattamente sulla forma e si smussano solo le onde. In movimento si disegna come una curva di Catmull-Rom chiusa; ferma, con archi esatti, e lascia il posto alla bolla vera, un elemento con border-radius. Quando niente si muove il ciclo si spegne.
All’invio una copia nascosta della textarea, con le stesse misure e uno span per parola, dice dove sta ogni parola; le parole passano in uno strato sopra tutto, nello stesso punto, nello stesso fotogramma in cui la textarea si svuota. La pelle del campo prende come meta il riquadro delle parole più il margine della bolla, con molle 1,9 volte più rigide e smorzamento 0,72, mentre il colore va dal grigio al giallo: in WRAP secondi il campo si è stretto intorno al messaggio.
Il messaggio vero è già al suo posto nella conversazione, trasparente. Dopo WRAP la meta della pelle è un riquadro a metà strada fra quello del campo e la bolla vera: x e larghezza seguono power3.inOut, y e altezza power3.out, così sale prima e scivola dopo, in LIFT secondi. I punti che stanno davanti nel verso del viaggio hanno le molle più rigide di quelli dietro (fino al 35% in più o in meno, dal prodotto fra la normale del punto e la direzione): la pelle si allunga mentre va e si schiaccia quando si ferma. Una pelle nuova esce dal pulsante, da un punto di 4 pixel, e si allarga nel campo.
Le parole non hanno una curva loro: ognuna sta a una distanza fissa dal centro della forma, che va da quella nel campo a quella nella bolla, e tutte si spostano di quanto il baricentro della pelle resta indietro rispetto alla sua meta. Così non escono mai dalla pelle, ondeggiano con lei e sono esattamente al loro posto quando è ferma. La bolla è larga al massimo quanto le righe del campo (max-width: calc(100% − 50px)), quindi gli a capo restano gli stessi e le parole viaggiano in blocco.
Prima di ogni cambio si legge dove sta ogni messaggio; dopo, ognuno riparte dal vecchio posto su una molla, i più bassi un po’ più rigidi, così la spinta sale per la conversazione. Quando la bolla arriva, i messaggi sopra ricevono una spinta verso l’alto di BUMP pixel al secondo, il 30% in meno per ognuno più su. I più vecchi svaniscono sotto l’intestazione (una maschera in cima) e oltre i quattordici se ne vanno.
La bozza è una bolla vera con le parole scritte fin lì in inchiostro trasparente: si misurano con getClientRects e non si vedono. Su ogni parola una barretta lunga come lei, un cursore dopo l’ultima, e intorno una pelle col contorno nel colore di chi scrive che segue la bolla mentre cresce; una parola che va a capo fa scivolare la sua barretta alla riga sotto. Il modo di scrivere si inventa una volta per risposta con un generatore col seme preso dal testo: raffiche a TYPING lettere al secondo, pause dopo virgole e punti, una parola scritta e cancellata. Mandata la risposta, il messaggio vero prende il posto della bozza e la sua pelle; il colore passa al grigio pieno mescolato con l’alfa premoltiplicata, una spinta dal centro la gonfia un attimo, le barrette svaniscono e le parole entrano da blur(5px). La conversazione è un role log con aria-live polite, ogni messaggio comincia con chi parla (nascosto alla vista) e la bozza è aria-hidden; un clic da script, l’anteprima della libreria, scrive un messaggio lettera per lettera senza prendere il focus e lo manda.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
WRAP | script.js | 0.16 | I secondi in cui la pelle del campo si stringe intorno alle parole, prima di partire. |
LIFT | script.js | 0.5 | I secondi del viaggio del messaggio dal campo al suo posto nella conversazione. |
SPRING | script.js | [420, 0.5] | Le molle della pelle: quanto sono rigide, e quanto smorzate, da 0 (ondeggia per sempre) a 1 (non ondeggia). |
TENSION | script.js | 0.5 | Quanto ogni punto della pelle si trascina dietro i vicini, da 0 a 1: più alto, più liscia. |
TYPING | script.js | 22 | Le lettere al secondo di un coinquilino che scrive la risposta. |
WAIT | script.js | 0.6 | I secondi fra l’arrivo del messaggio e l’inizio della risposta. |
BUMP | script.js | 130 | Quanto il messaggio che arriva spinge quelli sopra, in pixel al secondo. |
PEOPLE | script.js | ['Iris', 'Theo'] | I coinquilini, nei colori --who-1 e --who-2. |
REPLIES | script.js | [['milk', 'Theo', 'Guilty. Two cartons on my way home, promise.'], …] | Una parola da cercare nel mio messaggio, chi risponde e la risposta. |
OTHER | script.js | [['Iris', 'Ha, fair. Let’s talk about it tonight.'], …] | Le risposte a tutto il resto, una dopo l’altra. |
DEMO | script.js | ['Who finished the oat milk?', …] | Quello che l’anteprima della libreria scrive e manda, un messaggio per clic. |
Per la chat di un’app di gruppo o di coinquilini, il supporto di un negozio, un assistente che risponde, i commenti dal vivo, la demo di un’app di messaggi: ovunque il campo per scrivere e il momento dell’invio debbano avere un carattere.
La chat prende la larghezza dello schermo meno i margini (358 pixel a 390) e la bolla resta larga quanto le righe del campo; la textarea è a 16 pixel, così Safari su iPhone non ingrandisce la pagina, la tastiera mostra il tasto per inviare (enterkeyhint send) e il pulsante è un bersaglio di 44 pixel, che si abbassa sotto il dito.
Niente pelle che si stringe o viaggia: il messaggio compare al suo posto sfumando e il campo resta com’è; i messaggi non scivolano, la bozza cresce a parole senza che le barrette si spostino e la risposta compare sfumando.
GSAP 3.15.0, Rubik (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 17 KB; le librerie: GSAP 28 KB.
Provata il 6 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.