
Il pulsante da far scorrere
Pulsanti, Fisica, Transizioni
NuovaGratis
Un foglio che sale dal fondo dello schermo e si ferma a metà: si trascina col dito, oltre la cima si allunga come gomma e, lasciato, sceglie dove fermarsi da dove si trova e da quanto veloce andava; lanciato in giù si chiude.
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 bottom sheet</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/plus-jakarta-sans@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<button class="open" type="button" aria-haspopup="dialog" data-open data-autoclic>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 15V4.5M7.5 8.5 12 4l4.5 4.5M5 12.5v5.5a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2v-5.5"/></svg>
<span>Share</span>
</button>
</main>
<!-- the sheet: a real dialog (focus kept inside, Escape, the page behind out of reach) whose panel rises from the
bottom. It can be dragged: it stops at half height or at full height, stretches a little past the top and
closes when thrown down. The script moves it with a spring -->
<dialog class="sheet" aria-labelledby="sheet-title" data-sheet>
<div class="sheet__shade" data-shade></div>
<div class="sheet__panel" tabindex="-1" data-panel>
<button class="sheet__grab" type="button" aria-label="Show more" data-grab><span></span></button>
<div class="sheet__head">
<div>
<h2 class="sheet__title" id="sheet-title">Share this stay</h2>
<p class="sheet__sub">Two nights in the hills, from 14 November</p>
</div>
<button class="sheet__close" type="button" aria-label="Close" data-close>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 7l10 10M17 7 7 17"/></svg>
</button>
</div>
<div class="sheet__apps" data-half>
<button class="app" type="button" data-copy>
<span class="app__ring"><svg viewBox="0 0 24 24" aria-hidden="true" data-copy-icon><path d="M10 14a4.5 4.5 0 0 0 6.4 0l3-3a4.5 4.5 0 0 0-6.4-6.4l-1.2 1.2M14 10a4.5 4.5 0 0 0-6.4 0l-3 3a4.5 4.5 0 0 0 6.4 6.4l1.2-1.2"/></svg></span>
<span class="app__name" data-copy-label>Copy link</span>
</button>
<button class="app" type="button" data-action>
<span class="app__ring"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4.5 18.5V7a2.5 2.5 0 0 1 2.5-2.5h10A2.5 2.5 0 0 1 19.5 7v7a2.5 2.5 0 0 1-2.5 2.5H8.5z"/></svg></span>
<span class="app__name">Message</span>
</button>
<button class="app" type="button" data-action>
<span class="app__ring"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 6.5h16v11H4zM4.5 7l7.5 6 7.5-6"/></svg></span>
<span class="app__name">E-mail</span>
</button>
<button class="app" type="button" data-action>
<span class="app__ring"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 5h5v5H5zM14 5h5v5h-5zM5 14h5v5H5zM14 14h5v5h-5z"/></svg></span>
<span class="app__name">More</span>
</button>
</div>
<ul class="sheet__rows">
<li><button class="row" type="button" data-action><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 4.5h10v15l-5-3.5-5 3.5z"/></svg>Add to a list</button></li>
<li><button class="row" type="button" data-action><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7 3.5h7l4 4v13H7zM14 3.5v4h4M9.5 13h6M9.5 16.5h6"/></svg>Save as PDF</button></li>
<li><button class="row" type="button" data-action><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M7.5 9V4h9v5M7.5 17H5v-6.5a1.5 1.5 0 0 1 1.5-1.5h11a1.5 1.5 0 0 1 1.5 1.5V17h-2.5M7.5 14h9v6h-9z"/></svg>Print</button></li>
<li><button class="row" type="button" data-action><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4.5 4.5h6v6h-6zM13.5 4.5h6v6h-6zM4.5 13.5h6v6h-6zM14 14h2.5v2.5H14zM17 17h2.5v2.5H17z"/></svg>Show a QR code</button></li>
<li><button class="row row--quiet" type="button" data-action><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5.5 20V4.5M5.5 5h11l-2 4 2 4h-11"/></svg>Report a problem</button></li>
</ul>
</div>
</dialog>
<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.
25 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 foglio dal basso» da Animorio e adattala al mio sitoIl foglio sta in un dialog aperto con showModal(): il fuoco resta dentro (lo script lo porta sul pannello, da dove Tab raggiunge i pulsanti), Esc lo chiude e la pagina dietro non si raggiunge. Il dialog occupa tutto lo schermo ed è trasparente; dentro ci sono l’ombra scura e il pannello. L’evento cancel viene fermato e il foglio si chiude da sé a fine discesa.
Il pannello ha una sola posizione, y, contata dalla cima, e una molla con rigidità e smorzamento di SPRING che lo porta al punto scelto, calcolata sul ticker di GSAP a passi di 4 millisecondi. A ogni fotogramma l’ombra e il pulsante che arretra (SINK) seguono quanto foglio si vede.
Premere sul pannello lo ferma sotto il dito; dopo 6 pixel di movimento è un trascinamento e il puntatore viene catturato. Oltre la cima il pannello va avanti come STRETCH · (1 − 1/(0,55 · oltre/STRETCH + 1)), sempre meno e mai più di STRETCH; e per non lasciare vuoti sotto di sé continua 160 pixel oltre il bordo dello schermo.
Lasciato, la velocità viene dagli ultimi 90 millisecondi del trascinamento: lo script guarda dove sarebbe il pannello dopo THROW secondi a quella velocità e sceglie la fermata più vicina fra cima, metà e chiuso. La molla parte con la velocità del lancio, così il gesto continua nell’arrivo.
L’anteprima clicca un solo segno, data-autoclic, che lo script sposta: prima su Share, a foglio aperto sulla linguetta (che lo porta in cima), in cima sulla crocetta. Così l’anteprima apre, allarga e chiude da sola, sempre da capo.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
SPRING | script.js | [420, 0.86] | La molla del pannello: quanto è rigida e quanto è frenata (1 = senza rimbalzi). |
THROW | script.js | 0.18 | Quanto conta un lancio nello scegliere dove fermarsi, in secondi della sua velocità. |
STRETCH | script.js | 110 | Quanto si può allungare il pannello oltre la cima, al massimo, in pixel. |
SHADE | script.js | 1 | Quanto si scurisce la pagina dietro il pannello, da 0 a 1. |
SINK | script.js | 0.06 | Quanto arretra il pulsante Share mentre il foglio è aperto. |
PEEK | script.js | 30 | Quanto si vede, a metà altezza, di quello che viene dopo i pulsanti tondi, in pixel. |
Per condividere, per i filtri di una ricerca, per le opzioni di un elemento, per un carrello o un riepilogo: soprattutto al telefono, dove il pollice arriva comodo in fondo allo schermo.
Al telefono il foglio prende tutta la larghezza e lascia spazio alla barra in fondo dell’iPhone; si trascina col dito da qualsiasi punto, e due tocchi veloci non ingrandiscono la pagina. Se il contenuto è più alto dello schermo il foglio scorre col dito e si trascina solo dalla linguetta e dal titolo.
Il foglio compare e sparisce con una dissolvenza veloce invece di salire e scendere, passa da metà alla cima senza movimento e i pulsanti tondi non spuntano; trascinato, segue comunque il dito.
GSAP 3.15.0, Plus Jakarta Sans (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 7,3 KB; le librerie: GSAP 28 KB.
Provata il 3 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.