
Il menu che si apre dal pulsante
Menu, Transizioni, Testo
Gratis
Nello stile minimal: l’esportazione di 248 foto in un archivio, e la barra di avanzamento è la frase stessa, Exporting 248 photos to your archive. Man mano che il lavoro avanza le lettere passano da un filo a tutto il peso una dopo l’altra, come se la frase si stampasse, su un’onda di peso sfumata su quattro lettere, senza che la frase si sposti di un pixel. Sotto, la percentuale su rulli che girano e una linea sottile. Pausa, ripresa, la connessione persa che toglie l’inchiostro da dove si è fermata, e alla fine la frase si ricompone in 248 photos archived con le sue stesse lettere.
Una cartella che funziona da sola: index.html, style.css, script.js e le librerie da CDN.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The sentence that prints itself</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- a photo app exporting to an archive, and the progress bar is the sentence itself: as the work goes on its
letters go from a hairline to full weight one after the other, as if it were being printed, on a weight wave
a few letters soft. Under it the percentage on rolling figures and a thin line. Pause, resume, a lost
connection that lifts the ink back off, and at the end the sentence sets itself again from its own letters -->
<section class="ex" aria-label="Photo export" data-export>
<p class="ex__phrase" aria-hidden="true" data-phrase></p>
<p class="sr" data-words>Exporting 248 photos to your archive</p>
<div class="ex__row">
<span class="ex__pct" aria-hidden="true" data-pct></span>
<span class="ex__count" aria-hidden="true" data-count>0 of 248</span>
</div>
<div class="ex__line" role="progressbar" aria-label="Export" aria-valuemin="0" aria-valuemax="100"
aria-valuenow="0" aria-valuetext="Not started" data-line>
<span class="ex__track" data-track></span>
<span class="ex__fill" data-fill></span>
<span class="ex__mark" data-mark></span>
<span class="ex__head" data-head></span>
</div>
<div class="ex__foot">
<span class="ex__swap" data-status>Originals · 2.6 GB</span>
<button class="ex__btn" type="button" data-btn data-autoclic>
<span class="ex__btnfill" aria-hidden="true"></span>
<span class="ex__label" data-label>Export</span>
</button>
</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.
31 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 caricamento che annerisce la frase» da Animorio e adattala al mio sitoLa frase è spezzata in parole (flex con l’a capo) e ogni lettera è una cella larga quanto la lettera nel taglio sottile, wght 100 e wdth 125, misurata in em: la frase va a capo una volta sola e nello stesso modo per tutto il caricamento. Il buco fra le parole è uno spazio dello stesso taglio, misurato come differenza fra «n n» e «nn». La cella è l’elemento che GSAP sposta; la lettera dentro è quella a cui lo script cambia peso, larghezza, tono e affondo, così le due trasformazioni non si cancellano.
Una lettera più pesante è più larga. All’avvio lo script misura, per ogni lettera delle due frasi e per diciassette pesi fra 100 e 900, la larghezza wdth a cui la lettera è larga esattamente quanto la sua cella: una bisezione di undici passi, fatta per tutte le lettere insieme (ognuna ha il suo wdth di prova, poi si leggono tutte le larghezze), così ogni passo costa un solo calcolo dell’impaginazione e non uno per lettera. Durante il caricamento il wdth di ogni lettera si legge da questa tabella, interpolando fra due pesi: la O nera si stringe fino a circa 100, la i non ci riesce del tutto e sfora di mezzo pixel, coperto dai suoi margini.
Il lavoro fatto, da 0 a 1, diventa un fronte che corre sulla frase: per la lettera i l’obiettivo è smoothstep((p·(n + SOFT) − i) / SOFT), quindi SOFT lettere stanno a metà strada. Ogni lettera insegue il suo obiettivo con una molla appena sotto lo smorzamento critico (0,74), integrata a ogni fotogramma con un passo di al massimo 1/30 di secondo. Quando l’inchiostro supera il 90% la lettera riceve una spinta verso il basso su una molla più morbida (0,42), le vicine un terzo e un decimo: affonda di PRESS pixel e torna su con un assestamento. Quando la connessione si perde e il peso torna sotto il 40%, la spinta è piccola e verso l’alto.
Ogni cifra è un rullo con 0-9 e di nuovo 0 in una finestra alta una cifra, sfumata sopra e sotto con una maschera. Il rullo delle unità segue il conto intero della percentuale, quello delle decine il conto diviso dieci, quello delle centinaia diviso cento, su una molla: lo spostamento è il conto modulo dieci, quindi il passaggio da 9 a 10 gira in avanti senza salti. Un salto di più di sei cifre (il ritorno a zero) si fa dalla parte più corta. Un rullo che non serve si chiude in larghezza con un piccolo rimbalzo.
Le lettere comuni alle due frasi si trovano come fa un diff (Ratcliff e Obershelp): la sequenza comune più lunga, 248photos, poi la stessa ricerca a sinistra e a destra, che trova archive. Le lettere che restano si raggruppano in parole e volano con la tecnica FLIP: si misurano prima, si rifà l’impaginazione con la frase nuova, si misurano dopo e si parte dalla differenza. Una parola parte solo quando le parole che stanno dove deve andare se ne sono andate (un piccolo ordinamento topologico sui rettangoli), e una parola che cambia riga viaggia sulla più alta delle due: scendendo prima scorre e poi cala, salendo prima sale e poi scorre. Le lettere che se ne vanno restano dov’erano, tolte dal flusso con una posizione assoluta, e svaniscono salendo; quelle nuove si stampano al loro posto.
Un clic da script sul pulsante (detail 0, senza tastiera) fa partire il giro intero, più veloce di PREVIEW: pausa al 46%, ripresa, connessione persa, Retry, la frase finale e il ritorno a riposo, con un finto tocco sul pulsante a ogni passo; i tempi fra un passo e l’altro sono delayedCall di GSAP e gli altri clic da script durante il giro sono ignorati. Un clic vero ferma il giro e prende il comando. Quando niente si muove il ciclo esce dal ticker di GSAP e non ridisegna niente.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
PHRASE | script.js | 'Exporting 248 photos to your archive' | La frase mentre le foto vengono esportate: è lei la barra di avanzamento. |
DONE | script.js | '248 photos archived' | La frase alla fine, ricomposta con le lettere che ha in comune con la prima. |
PHOTOS | script.js | 248 | Quante foto vengono esportate (il conto sotto la frase). |
SIZE_GB | script.js | 2.6 | Quanto pesa l’esportazione, in gigabyte. |
SECONDS | script.js | 6 | Quanti secondi dura un’esportazione nella demo (una vera segue i suoi byte). |
WEIGHT | script.js | [100, 900] | Il peso (wght) di una lettera non ancora stampata e di una stampata. |
WIDTH | script.js | 125 | La larghezza (wdth) delle lettere sottili: quelle stampate si stringono quanto basta per restare al loro posto. |
SOFT | script.js | 4 | Su quante lettere è sfumato il bordo dell’onda di peso. |
PRESS | script.js | 1.2 | Di quanti pixel affonda una lettera quando arriva l’inchiostro. |
FAIL_EVERY | script.js | 2 | Un’esportazione ogni quante perde la connessione (0 mai). |
FAIL | script.js | [0.72, 0.5] | Dove si perde la connessione e fin dove torna indietro l’inchiostro (le foto tenute), da 0 a 1. |
PREVIEW | script.js | [1.7, 0.46] | Nel giro dell’anteprima: quante volte più veloce, e dove si mette in pausa. |
LABELS | script.js | ['Export', 'Pause', 'Resume', 'Retry', 'Export again'] | Le parole del pulsante, stato per stato. |
--ink | style.css | #f4f1ea | Le lettere stampate, le cifre e la linea. |
--light | style.css | #a8a49c | Le lettere non ancora stampate. |
--accent | style.css | #ff5a2a | La testa della linea e quello che è andato storto. |
Per un’esportazione, un caricamento o un backup in un’app di foto o di documenti, per la pubblicazione di un articolo, per l’invio di un ordine o di un modulo, per ogni attesa in cui la frase che dice cosa succede può essere essa stessa l’avanzamento.
Il componente prende tutta la larghezza meno i margini (fino a 400 pixel) e la frase si rimpicciolisce col telefono, con le celle in em, quindi va a capo come sul computer e non si sposta mai; le animazioni sono le stesse. Il pulsante risponde al tocco come al mouse: si riempie e la scritta si allarga mentre il dito preme. Se la finestra cambia misura mentre la frase si ricompone, la ricomposizione salta alla fine.
Niente si sposta: il peso delle lettere cambia lo stesso, perché è l’avanzamento, ma senza molla e senza affondo; le cifre cambiano senza girare, le righe cambiano in dissolvenza e la frase finale arriva in dissolvenza invece di ricomporsi a lettere in volo.
GSAP 3.15.0, Archivo (font variabile, assi wght e wdth) 5.3.0.
Compressi con gzip, i tre file della demo pesano 13 KB; le librerie: GSAP 28 KB.
Provata il 16 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.