
Il banner dei cookie
Consenso, Transizioni, SVG, Fisica
NuovaGratis
Un menu a tutto schermo che arriva come un ascensore d’acciaio: a riposo c’è solo il pulsante di chiamata, d’acciaio spazzolato con un anello di luce che si accende. Premuto, compare la cabina e le porte telescopiche a due velocità si aprono, con le ante davanti che corrono il doppio di quelle dietro; sopra, un quadrante a lancetta con i nomi delle sezioni al posto dei piani. Scegliendo una voce le porte si chiudono, la lancetta viaggia fino a quella sezione con un rimbalzo e le porte si riaprono.
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 elevator menu</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">
<!-- the elevator menu: at rest only a brushed steel call button with a ring of light. Pressed, the lift arrives:
a steel portal with a floor dial over two speed telescopic doors, which open on the cabin and the menu.
Choosing a section, the doors shut, the needle travels to it on the dial and the doors open again -->
<div class="lift" data-lift>
<!-- the call button: the Menu toggle. Open, it moves up into the portal and closes the doors -->
<button class="call" type="button" aria-expanded="false" aria-controls="lift-menu" data-call data-autoclic>
<span class="call__plate" aria-hidden="true">
<span class="call__ring"></span>
<span class="call__face">
<svg class="call__icon call__icon--open" viewBox="0 0 24 24"><path d="M12 5v14"/><path d="M3.5 12L9 7.5v9zM20.5 12L15 7.5v9z"/></svg>
<svg class="call__icon call__icon--close" viewBox="0 0 24 24"><path d="M12 5v14"/><path d="M9.5 12L4 7.5v9zM14.5 12L20 7.5v9z"/></svg>
</span>
<span class="call__label" data-word>Menu</span>
</span>
<span class="sr" data-name>Open the menu</span>
</button>
<!-- the portal: the dial, the doors, the cabin behind them -->
<div class="car" data-car inert>
<div class="car__head">
<svg class="dial" viewBox="0 0 300 168" aria-hidden="true" data-dial>
<defs>
<radialGradient id="lift-face" cx="0.5" cy="1" r="1">
<stop offset="0" stop-color="#2a2622"/>
<stop offset="0.7" stop-color="#14120f"/>
<stop offset="1" stop-color="#0b0a09"/>
</radialGradient>
<linearGradient id="lift-brass" x1="0" x2="1" y1="0" y2="1">
<stop offset="0" stop-color="#f6dc9c"/>
<stop offset="0.45" stop-color="#c2963f"/>
<stop offset="1" stop-color="#6e4f1a"/>
</linearGradient>
<filter id="lift-glow" x="-40%" y="-80%" width="180%" height="260%">
<feGaussianBlur stdDeviation="2.4" result="b"/>
<feMerge><feMergeNode in="b"/><feMergeNode in="SourceGraphic"/></feMerge>
</filter>
</defs>
<path class="dial__rim" d="M4 160A146 146 0 0 1 296 160Z"/>
<path class="dial__face" d="M12 158A138 138 0 0 1 288 158Z" fill="url(#lift-face)"/>
<g class="dial__ticks" data-ticks></g>
<g class="dial__names" data-names></g>
<path class="dial__dir" d="M34 139l8 11 8-11z" data-dir="-1"/>
<path class="dial__dir" d="M250 150l8-11 8 11z" data-dir="1"/>
<g class="dial__needle" data-needle>
<path d="M150 158L147.4 153 150 66 152.6 153Z" fill="url(#lift-brass)"/>
<path d="M150 158l-5 9h10z" fill="#6e4f1a"/>
</g>
<path class="dial__hub" d="M128 160A22 22 0 0 1 172 160Z" fill="url(#lift-brass)"/>
</svg>
<span class="car__slot" aria-hidden="true" data-slot></span>
</div>
<div class="car__opening" data-opening>
<div class="cabin">
<span class="cabin__light" aria-hidden="true"></span>
<span class="cabin__rail" aria-hidden="true"></span>
<nav class="menu" id="lift-menu" aria-label="Main" data-menu>
<ul class="menu__list">
<li><a class="floor" href="#" aria-current="page" data-floor><span class="floor__name">Lobby</span><span class="floor__note">Start here</span></a></li>
<li><a class="floor" href="#" data-floor><span class="floor__name">Work</span><span class="floor__note">Selected projects</span></a></li>
<li><a class="floor" href="#" data-floor><span class="floor__name">Studio</span><span class="floor__note">Who we are</span></a></li>
<li><a class="floor" href="#" data-floor><span class="floor__name">Journal</span><span class="floor__note">Notes and essays</span></a></li>
<li><a class="floor" href="#" data-floor><span class="floor__name">Contact</span><span class="floor__note">Say hello</span></a></li>
</ul>
</nav>
</div>
<!-- two speed telescopic doors: on each side a slow panel and a fast one in front of it -->
<span class="door door--slow door--left" aria-hidden="true" data-door="-1"><span class="door__sheen"></span></span>
<span class="door door--slow door--right" aria-hidden="true" data-door="1"><span class="door__sheen"></span></span>
<span class="door door--fast door--left" aria-hidden="true" data-door="-2"><span class="door__sheen"></span></span>
<span class="door door--fast door--right" aria-hidden="true" data-door="2"><span class="door__sheen"></span></span>
<span class="car__pass" aria-hidden="true" data-pass></span>
</div>
<span class="car__sill" aria-hidden="true"></span>
</div>
<p class="sr" aria-live="polite" data-live></p>
</div>
</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.
29 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 menu dell’ascensore» da Animorio e adattala al mio sitoLe porte, il portale e la piastra sono acciaio fatto solo di gradienti: una sfumatura di base nel verso della lunghezza e tre repeating-linear-gradient sottili, chiari e scuri, con passi di 3, 7 e 13 pixel che non si ripetono insieme, così le righe della spazzolatura sembrano irregolari. La faccia del pulsante è un conic-gradient (l’acciaio tornito) sotto un repeating-radial-gradient di cerchi; il suo angolo è una proprietà registrata con @property, così sotto il puntatore il riflesso gira in una transizione.
Le quattro ante sono larghe un quarto dell’apertura. Un solo numero va da 0 (chiuse) a 1 (aperte): le ante dietro si spostano di una larghezza d’anta per quel numero, quelle davanti di due, quindi nello stesso tempo corrono il doppio e alla fine stanno una sull’altra fuori dall’apertura, che taglia con overflow: hidden. Le ante davanti hanno l’ombra sul bordo e la gomma dove si incontrano.
Dentro ogni anta (con overflow: hidden) c’è uno strato col riflesso, largo quanto tutta l’apertura e spostato a sinistra di quanto l’anta è lontana dal bordo (--px); a ogni fotogramma lo script lo trasla all’indietro di quanto si sposta l’anta, con un transform che lavora sul compositore senza ridipingere. Così il riflesso sta fermo nella stanza, come in uno specchio vero, e sono le ante a scorrergli sotto; le quattro ante insieme lo mostrano intero quando sono chiuse.
Il quadrante è un SVG: le tacche e i nomi si mettono sull’arco dalle voci del menu, a SWEEP gradi in tutto, fuori dalla corsa della lancetta così nessun nome è mai coperto. Viaggiando, una timeline sposta il bersaglio della lancetta da un piano all’altro in FLOOR secondi per piano, e la lancetta lo segue su una molla smorzata (STIFF, DAMP) in un ciclo a passi di 1/30 di secondo: resta un poco indietro, supera il nome e torna. Il nome sotto la lancetta si accende, come i piani di un vecchio indicatore.
GSAP fa le tre scene: l’arrivo (il portale compare e il pulsante vola nel suo posto con un FLIP, misurato fra la sua posizione e quella di un segnaposto nel portale), il viaggio (porte chiuse, freccia accesa, una luce che passa sulle porte per ogni piano, il sobbalzo dell’arrivo, porte aperte) e la partenza. Il menu è inert finché le porte non sono aperte a metà, il pulsante ha aria-expanded, Esc chiude e rimette il fuoco sul pulsante, e chi usa la tastiera trova il fuoco sulla voce corrente appena le porte si aprono.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
OPEN | script.js | 1.15 | I secondi che le porte impiegano ad aprirsi. |
SHUT | script.js | 0.8 | I secondi che impiegano a chiudersi. |
FLOOR | script.js | 0.4 | I secondi di viaggio per ogni piano. |
STIFF | script.js | 120 | Quanto forte la molla tira la lancetta dove è la cabina. |
DAMP | script.js | 0.3 | Quanto è frenata la lancetta: basso, rimbalza di più arrivando. |
SWEEP | script.js | 140 | L’ampiezza dell’arco del quadrante, in gradi. |
SHEEN | script.js | 1 | Quanto è forte il riflesso sulle porte (0 = niente). |
Per il sito di un hotel, di uno studio di architettura, di un palazzo d’uffici, di un’agenzia con un debole per il design d’epoca: dove aprire il menu può essere un piccolo viaggio e l’acciaio c’entra. Le sezioni devono essere poche (da tre a sei) perché stiano sul quadrante. Per un sito di tutti i giorni è troppo: il viaggio chiede qualche secondo.
Il portale prende tutta la larghezza e diventa alto, con montanti più sottili, un quadrante più piccolo e il pulsante Close accanto; le ante restano quattro e il menu sta nella cabina senza sforare. Il tocco apre, sceglie e chiude; l’anello si accende alla pressione invece che al passaggio del mouse.
Niente scorre: il portale e il pulsante compaiono in dissolvenza già al loro posto, le porte svaniscono invece di aprirsi e ricompaiono invece di chiudersi, la lancetta salta sul piano nuovo senza molla e senza viaggio, senza la luce che passa e senza sobbalzo.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 9,6 KB; le librerie: GSAP 28 KB.
Provata il 5 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.