
Le storie a cubo
Storie, 3D, Transizioni
NuovaGratis
L’ottimizzazione delle immagini di un sito come un cubo da puzzle 3x3 in CSS 3D: a riposo è mescolato, e mentre le 248 immagini vengono alleggerite si risolve una mossa dopo l’altra, ogni mossa uno strato che gira di un quarto con un piccolo rimbalzo. L’ultima mossa chiude tutte le facce, gli adesivi lampeggiano e il cubo fa un saltello e una mezza giravolta soddisfatta; Run again lo rimescola con una raffica di mosse veloci.
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, viewport-fit=cover">
<title>The solving cube</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/standard.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/geist-mono@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the image optimizer of a website, as a 3x3 puzzle cube in CSS 3D. At rest the cube is scrambled; pressed, it
solves itself one move at a time as the images are done, every move a layer turning a quarter with a little
bounce, and the last one closes every face. The 27 small cubes are built by script.js -->
<section class="opt" aria-labelledby="opt-title" data-opt>
<div class="opt__scene" role="progressbar" aria-labelledby="opt-title" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" aria-valuetext="Not started" data-scene>
<div class="opt__shadow" aria-hidden="true" data-shadow></div>
<div class="opt__lift" aria-hidden="true" data-lift>
<div class="cube" data-cube></div>
</div>
</div>
<div class="opt__head">
<div class="opt__words">
<h2 class="opt__title" id="opt-title"><span class="opt__swap" data-title>Optimize images</span></h2>
<p class="opt__meta"><span class="opt__swap" data-meta>248 images · 64.2 MB</span></p>
</div>
<p class="opt__figure" aria-hidden="true">
<span class="opt__pct is-quiet" data-pct>0%</span>
<svg class="opt__tick" viewBox="0 0 24 24" data-tick><path d="M5.5 12.6l4.1 4.1L18.6 7.4" pathLength="1"/></svg>
</p>
</div>
<div class="opt__foot">
<p class="opt__file" aria-hidden="true"><span class="opt__swap" data-file>To AVIF and WebP</span></p>
<button class="opt__btn" type="button" data-action data-autoclic><span class="opt__label" data-label>Optimize</span></button>
</div>
<p class="sr" role="status" 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.
30 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 cubo che si risolve» da Animorio e adattala al mio sitoIl cubo è fatto di 27 cubetti, ognuno un div con sei facce in CSS 3D (preserve-3d e backface-visibility hidden). Ogni cubetto sa dov’è sulla griglia 3x3x3 (tre interi fra −1 e 1) e com’è girato (una matrice di rotazione 3x3 di numeri interi). Le facce che stanno fuori dal cubo grande hanno l’adesivo del colore di quella faccia; quelle di dentro sono plastica nera, e si vedono nella fessura quando uno strato gira. Anche il cubetto al centro c’è: senza, a metà mossa si vedrebbe un buco.
Una mossa sceglie un asse, uno strato (−1 o 1) e un verso. Mentre suona, i nove cubetti di quello strato ricevono una rotazione in più attorno all’asse, con l’angolo animato da GSAP con back.out (il piccolo rimbalzo). Alla fine la rotazione esatta di un quarto, arrotondata a interi, moltiplica la matrice e la posizione di ognuno: niente errori che si accumulano, e dopo cento mosse il cubo è ancora perfetto. Le trasformazioni sono scritte a mano come matrix3d, così quello che vedi è proprio quello che lo script calcola.
La mescolata è un elenco di mosse a caso, mai due sullo stesso asse di fila, così nessuna annulla o ripete quella prima. La soluzione è lo stesso elenco letto dalla fine, con ogni mossa nell’altro verso: l’ultima riporta per forza ogni cubetto a casa. Le mosse sono legate alle immagini: dopo k immagini su N ne sono state fatte k ÷ N di tutte, ma l’ultima solo quando l’ultima immagine è finita, così il cubo si chiude proprio al 100%. Se il lavoro corre più delle mosse, le mosse in coda accelerano.
A ogni fotogramma in cui qualcosa si muove, la normale di ogni faccia passa per la rotazione del suo cubetto, per quella dello strato che gira e per quella della vista (e per l’inclinazione verso il puntatore). Il prodotto con la direzione della lampada dà l’ombra, un velo nero sopra la faccia; il prodotto col vettore a metà fra la lampada e chi guarda, elevato alla diciottesima, dà il riflesso sull’adesivo. Lo script scrive solo i valori che cambiano, e quando niente si muove non ridisegna.
Quando uno strato gira, il resto del cubo gira di un paio di gradi nel verso opposto attorno allo stesso asse e torna con una molla elastica, come in mano. All’avvio il cubo salta e gira di un quarto con back.inOut mentre le immagini vengono lette; alla fine lampeggia (una variabile CSS che schiarisce tutti gli adesivi), salta e fa mezzo giro con back.out, e ricade con bounce.out mentre la sua ombra si stringe e torna.
Il cubo è un role=progressbar con aria-valuenow e aria-valuetext (quante immagini su quante), il pannello ha aria-busy mentre lavora e una riga aria-live dice quando il lavoro parte, si ferma e finisce. Il pulsante cambia parola (Optimize, Pause, Resume, Run again) e la pillola prende la larghezza nuova con un piccolo rimbalzo; un clic da script, quello dell’anteprima della libreria, non mette mai in pausa.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
IMAGES | script.js | 248 | Quante immagini passa l’ottimizzazione. |
SECONDS | script.js | 7 | Quanto dura un giro nella demo, in secondi (uno vero segue le sue immagini). |
MOVES | script.js | 12 | Quante mosse ha la mescolata, e quindi quante ne servono per risolverlo. |
CUBIE | script.js | 34 | La misura di un cubetto, in pixel. |
TURN | script.js | 0.34 | Quanto dura una mossa, in secondi. |
BOUNCE | script.js | 1.8 | Quanto va oltre uno strato prima di fermarsi: 0 per niente. |
TILT | script.js | 1 | Quanto il cubo si inclina verso il puntatore: 0 per niente. |
WEIGHT | script.js | 64.2 | Quanto pesano le immagini prima, in megabyte. |
SAVED | script.js | 0.6 | Quanta parte del peso si risparmia, da 0 a 1. |
Per un lavoro di qualche secondo fatto di tanti pezzi uguali che alla fine «tornano a posto»: ottimizzare o convertire delle immagini, riordinare una libreria, deduplicare dei file, ricostruire un indice. Il cubo dice bene «disordine che diventa ordine»; per un caricamento di cui non si conosce la durata è meglio un indicatore senza percentuale.
Il pannello prende la larghezza dello schermo meno 32 pixel (358 a 390) e resta alto 330; il cubo ha la stessa misura, perché sta largo nel suo spazio. Senza mouse il cubo non si inclina, tutto il resto è uguale: le stesse mosse, gli stessi rimbalzi e la stessa luce. Il pulsante è una pillola alta 36: col dito si schiaccia e rimbalza, e la scritta si allarga sull’asse della larghezza solo sotto il mouse.
Gli strati non girano: ogni mossa scatta già fatta, una alla volta, così si vede lo stesso il cubo che si mette in ordine. Niente saltelli, niente giravolte, niente inclinazione né contraccolpo; la rimescolata è immediata, alla fine gli adesivi lampeggiano solo in dissolvenza e la spunta e le parole nuove arrivano in dissolvenza.
GSAP 3.15.0, Instrument Sans (font variabile) 5.3.0, Geist Mono (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 11 KB; le librerie: GSAP 28 KB.
Provata il 8 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.