
Il banner dei cookie
Consenso, Transizioni, SVG, Fisica
NuovaGratis
Scorri dentro l’anteprima
Una barra di navigazione nera e larga che, scorrendo la pagina, si raccoglie in una pillola galleggiante come la Dynamic Island dell’iPhone, col nome della sezione che stai leggendo. Passandoci sopra, o toccandola, si gonfia su una molla in un pannello con le voci e il caricamento in corso; mentre i file salgono, dalla pillola si stacca una bolla con un anello che si riempie, tirando un collo di liquido che si spezza.
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 bar that becomes an island</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/inter-tight@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- the navigation: a wide black bar at the top of the page that, scrolling, gathers itself into a floating pill
like the Dynamic Island. Pointed at or tapped, the pill swells into a panel with the links; while the upload
runs, a bubble buds off it with a ring that fills. Four layers of content take turns inside the one shape -->
<header class="top">
<nav class="island" aria-label="Main" data-island>
<!-- the bubble that buds off the island while the upload runs, and the liquid neck between them -->
<svg class="island__goo" aria-hidden="true" data-goo>
<path class="island__neck" data-neck/>
<circle class="island__bud" r="0" data-bud/>
</svg>
<div class="island__shape" data-shape>
<!-- the wide bar: the upload's chip, the links, the account -->
<div class="wide" data-layer="wide">
<span class="chip" aria-hidden="true" data-chip>
<svg class="ring ring--chip" viewBox="0 0 36 36"><path class="ring__track" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28"/><path class="ring__fill" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28" pathLength="1" data-ring/><path class="ring__check" d="M12.5 18.5l3.6 3.6 7.4-7.6" pathLength="1"/></svg>
<span class="chip__text" data-chip-text>Uploading</span>
</span>
<ul class="wide__links">
<li><a href="#features" data-go>Features</a></li>
<li><a href="#pricing" data-go>Pricing</a></li>
<li><a href="#changelog" data-go>Changelog</a></li>
<li><a href="#">Docs</a></li>
</ul>
<div class="wide__end">
<a class="wide__signin" href="#">Sign in</a>
<a class="cta cta--light" href="#">Start free</a>
<button class="wide__menu" type="button" aria-expanded="false" aria-controls="island-menu" aria-label="Open the menu" data-menu>
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 9h14M5 15h14"/></svg>
</button>
</div>
</div>
<!-- the island: the menu's two lines and the section you are reading -->
<button class="compact" type="button" aria-expanded="false" aria-controls="island-menu" aria-label="Open the menu" data-layer="compact" data-toggle>
<svg class="compact__icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M5 9h14M5 15h14"/></svg>
<span class="compact__label" aria-hidden="true" data-label-box><span class="compact__ghost" data-ghost></span></span>
</button>
<!-- the island saying something for a moment: an upload starting, files synced -->
<div class="notice" data-layer="notice">
<span class="notice__icon"><svg class="ring ring--notice" viewBox="0 0 36 36" aria-hidden="true"><path class="ring__track" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28"/><path class="ring__fill" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28" pathLength="1" data-ring/><path class="ring__check" d="M12.5 18.5l3.6 3.6 7.4-7.6" pathLength="1"/></svg></span>
<span class="notice__text"><b data-notice-title>Uploading 3 files</b><small data-notice-sub>To the team folder</small></span>
</div>
<!-- the open island: the live activity, the links, the account -->
<div class="open" id="island-menu" data-layer="open">
<div class="act">
<span class="act__ring">
<svg class="ring ring--act" viewBox="0 0 36 36" aria-hidden="true"><path class="ring__track" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28"/><path class="ring__fill" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28" pathLength="1" data-ring/><path class="ring__check" d="M12.5 18.5l3.6 3.6 7.4-7.6" pathLength="1"/></svg>
<span class="act__pct" aria-hidden="true" data-pct>0</span>
</span>
<span class="act__text">
<b data-act-title>Ready to sync</b>
<small data-act-sub>3 files waiting</small>
</span>
<button class="act__btn" type="button" data-act-btn>Upload</button>
</div>
<ul class="open__links">
<li><a href="#features" data-go><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4.5 4.5h6v6h-6zM13.5 4.5h6v6h-6zM4.5 13.5h6v6h-6zM13.5 13.5h6v6h-6z"/></svg>Features</a></li>
<li><a href="#pricing" data-go><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M3.8 12.6V4.5h8.1l8.3 8.3-8.1 8.1zM8.3 8.6h.01"/></svg>Pricing</a></li>
<li><a href="#changelog" data-go><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M12 7.5V12l3 2M20.5 12a8.5 8.5 0 1 1-17 0 8.5 8.5 0 0 1 17 0z"/></svg>Changelog</a></li>
<li><a href="#"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M5 4.5h9.5L19 9v10.5H5zM14.5 4.5V9H19M8.5 13h7M8.5 16.5h5"/></svg>Docs</a></li>
</ul>
<div class="open__end">
<a class="open__signin" href="#">Sign in</a>
<a class="cta cta--light" href="#">Start free</a>
</div>
</div>
</div>
<span class="bud" aria-hidden="true" data-bud-ring>
<svg class="ring ring--bud" viewBox="0 0 36 36"><path class="ring__track" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28"/><path class="ring__fill" d="M18 4a14 14 0 1 1 0 28a14 14 0 1 1 0-28" pathLength="1" data-ring/><path class="ring__arrow" d="M18 23V13.4M14 17.2l4-4 4 4"/></svg>
</span>
</nav>
</header>
<main class="read">
<!-- a plain column to scroll under the bar: each section is a name the island shows while you read it -->
<section id="overview" data-section="Overview">
<h2>Overview</h2>
<p>Files saved on one device are on the others a few seconds later, and in the shared folder as soon as the team needs them.</p>
<p>There is nothing to set up: it keeps going in the background while you work.</p>
</section>
<section id="features" data-section="Features">
<h2>Features</h2>
<p>Changes travel in small pieces, so a large file that changed by one line sends only that line.</p>
<p>Every earlier version is kept for a year, and any of them comes back in one click.</p>
</section>
<section id="pricing" data-section="Pricing">
<h2>Pricing</h2>
<p>One plan for a single person and one for teams, paid by the seat and not by the gigabyte.</p>
<p>Either can be cancelled at the end of any month, and the files stay where they are.</p>
</section>
<section id="changelog" data-section="Changelog">
<h2>Changelog</h2>
<p>Uploads now carry on when you leave the page, and their progress shows in the bar at the top.</p>
<p>A folder with thousands of small files now arrives in one go instead of one file at a time.</p>
</section>
</main>
<p class="sr" aria-live="polite" data-live></p>
<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.
57 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 barra che diventa isola» da Animorio e adattala al mio sitoL’isola è un solo elemento nero: lo script gli scrive larghezza, altezza, raggio degli angoli e posizione a ogni fotogramma. Dentro ci sono quattro strati di contenuto, ognuno della sua misura e centrato: la barra larga, la pillola, l’annuncio e il pannello aperto. Lo strato che arriva appare con una sfocatura che si scioglie dopo 0,1 secondi, quello che se ne va sparisce in 0,14 e diventa inert, così il Tab non ci entra.
Larghezza, altezza, angoli e posizione sono molle sul ticker di GSAP, con la rigidità e lo smorzamento di SPRING e il passo limitato a 1/30 di secondo. Altezza e angoli hanno una rigidità più bassa (0,62 volte) della larghezza: l’isola prima si allarga e poi si gonfia, come quella dell’iPhone, invece di scalare tutta insieme.
La bolla è un cerchio in un SVG dietro l’isola, che parte dal cerchio dell’angolo destro della pillola e va a destra su una molla più morbida. Fra i due cerchi lo script ridisegna a ogni fotogramma un collo: due curve di Bézier che lasciano ogni cerchio con un’apertura che si stringe man mano che si allontanano, chiuse da un arco sulla bolla. Prima la bolla viene lanciata oltre la lunghezza del collo (NECK), così il collo si spezza, poi si posa a BUD[0] pixel; il collo si riattacca solo quando la bolla tocca di nuovo l’isola.
A ogni scorrimento lo script guarda quale sezione ha superato il 30% dello schermo e mette il suo data-section nella pillola: la parola vecchia sale e si sfoca, la nuova arriva da sotto. La larghezza della pillola si misura su una copia invisibile della parola nuova, così la molla parte subito verso la misura giusta. Sopra SHRINK pixel la barra diventa isola, sotto metà di SHRINK torna larga: lo scarto evita che tremi sul confine.
Il caricamento finto è una timeline di sei tratti che insieme durano UPLOAD secondi, a strappi come uno vero: parte da solo dopo AUTOPLAY[0] secondi, riparte AUTOPLAY[1] secondi dopo la fine, e il pulsante del pannello lo ferma o lo fa ripartire. Ogni fotogramma, se è cambiato, aggiorna gli anelli (stroke-dashoffset su un tracciato che parte da mezzogiorno), la percentuale, il file che sta salendo (il primo di FILES non ancora mandato per intero) e i MB che mancano, nella pastiglia della barra, nel pannello dell’isola e nella bolla. All’inizio e alla fine l’isola parla per NOTICE secondi.
Col mouse l’isola si apre passandoci sopra e si chiude GRACE secondi dopo che il puntatore è uscito; col dito, o con la tastiera, il pulsante dell’isola apre e chiude. Invio apre e porta il fuoco dentro il pannello, Esc chiude e lo riporta sull’isola, un tocco fuori chiude, e chiude anche lo scorrimento della pagina. Un aria-live dice inizio e fine del caricamento; l’annuncio non prende il posto della pillola mentre qualcuno ci sta lavorando con la tastiera.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
SPRING | script.js | [240, 0.62] | La molla dell’isola: quanto è rigida, e quanto è frenata (1 = senza rimbalzo). |
SHRINK | script.js | 80 | Dopo quanti pixel di scorrimento la barra diventa isola. |
PILL | script.js | 38 | L’altezza dell’isola, in pixel. |
BUD | script.js | [8, 0.92] | La bolla del caricamento: lo spazio fra lei e l’isola in pixel, e la sua misura rispetto all’altezza dell’isola. |
NECK | script.js | 20 | Di quanti pixel si allunga il collo di liquido prima di spezzarsi. |
UPLOAD | script.js | 6 | I secondi del caricamento finto. |
AUTOPLAY | script.js | [1.6, 5] | Il caricamento parte da solo dopo questi secondi, e riparte questi secondi dopo la fine (0 = solo a mano). |
NOTICE | script.js | 2.2 | I secondi in cui l’isola annuncia l’inizio o la fine del caricamento. |
GRACE | script.js | 0.3 | I secondi che l’isola aperta aspetta, uscito il puntatore, prima di chiudersi. |
FILES | script.js | 3 file | I file del caricamento finto: nome e misura in MB. |
Per la navigazione di un sito di prodotto o di un’app web con qualcosa che succede mentre si legge: un caricamento, un’esportazione, un ordine in consegna, una chiamata, un timer. Dove non c’è un’attività dal vivo basta la barra che si stringe in isola con il nome della sezione.
La barra larga tiene solo la pastiglia del caricamento, Start free e il pulsante del menu, che apre lo stesso pannello dell’isola; l’isola si apre e si chiude col tocco, e un tocco sulla bolla o sull’annuncio la apre. A 390 pixel la barra e il pannello sono larghi lo schermo meno 24 pixel e niente sfora; il nome di un file troppo lungo per il pannello finisce coi puntini.
Niente molle e niente collo di liquido: l’isola cambia misura di colpo, con una dissolvenza veloce di forma e contenuto; la bolla compare accanto alla pillola già al suo posto. Il nome della sezione e le scritte cambiano in dissolvenza, gli anelli si riempiono lo stesso, i collegamenti saltano alla sezione senza scorrere.
GSAP 3.15.0, Inter Tight (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 12 KB; le librerie: GSAP 28 KB.
Provata il 4 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.