
Il menu col bruco
Menu, Hover, Transizioni
NuovaGratis
Nello stile minimal: i filtri di un portfolio, All, Identity, Editorial, Packaging e Motion. La scheda scelta non è sottolineata ma chiusa da quattro segni di taglio vermigli, come un foglio pronto per la taglierina: cambiando scheda i quattro angoli partono uno dopo l’altro, ognuno sulla sua molla, e si ricompongono attorno alla parola nuova, che prende peso; sotto, i progetti scivolano al loro posto nuovo.
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 crop mark tabs</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 filters of a design studio's work. The chosen filter is not underlined: four printer's crop marks stand
off its corners, as on a sheet ready for the guillotine. Choosing another, the four marks travel apart, each
on its own spring, and close in again around the new word; the projects below move to their new places
(FLIP), the ones that leave fade and the ones that arrive breathe in. The marks are drawn by the script -->
<div class="folio" data-folio>
<div class="filters" role="tablist" aria-label="Filter the work" data-tabs>
<svg class="marks" aria-hidden="true" data-marks><path data-marks-path /></svg>
<button class="tab" type="button" role="tab" id="tab-all" aria-controls="work" aria-selected="true" data-filter="all"><span class="tab__label"><span class="tab__word" data-word>All</span><sup class="tab__n">6</sup></span><span class="tab__ghost" aria-hidden="true"><span class="tab__word">All</span><sup class="tab__n">6</sup></span></button>
<button class="tab" type="button" role="tab" id="tab-identity" aria-controls="work" aria-selected="false" tabindex="-1" data-filter="identity"><span class="tab__label"><span class="tab__word" data-word>Identity</span><sup class="tab__n">3</sup></span><span class="tab__ghost" aria-hidden="true"><span class="tab__word">Identity</span><sup class="tab__n">3</sup></span></button>
<button class="tab" type="button" role="tab" id="tab-editorial" aria-controls="work" aria-selected="false" tabindex="-1" data-filter="editorial"><span class="tab__label"><span class="tab__word" data-word>Editorial</span><sup class="tab__n">2</sup></span><span class="tab__ghost" aria-hidden="true"><span class="tab__word">Editorial</span><sup class="tab__n">2</sup></span></button>
<button class="tab" type="button" role="tab" id="tab-packaging" aria-controls="work" aria-selected="false" tabindex="-1" data-filter="packaging"><span class="tab__label"><span class="tab__word" data-word>Packaging</span><sup class="tab__n">2</sup></span><span class="tab__ghost" aria-hidden="true"><span class="tab__word">Packaging</span><sup class="tab__n">2</sup></span></button>
<button class="tab" type="button" role="tab" id="tab-motion" aria-controls="work" aria-selected="false" tabindex="-1" data-filter="motion"><span class="tab__label"><span class="tab__word" data-word>Motion</span><sup class="tab__n">2</sup></span><span class="tab__ghost" aria-hidden="true"><span class="tab__word">Motion</span><sup class="tab__n">2</sup></span></button>
</div>
<section class="work" id="work" role="tabpanel" aria-labelledby="tab-all" tabindex="0" data-work>
<article class="card" data-tags="identity packaging" style="--wdth: 62; --wght: 820">
<p class="card__meta"><span class="card__tags"><span data-tag="identity">Identity</span> · <span data-tag="packaging">Packaging</span></span><span class="card__year">2026</span></p>
<h2 class="card__name" data-name>Corlett Bakery</h2>
</article>
<article class="card" data-tags="editorial" style="--wdth: 118; --wght: 280">
<p class="card__meta"><span class="card__tags"><span data-tag="editorial">Editorial</span></span><span class="card__year">2025</span></p>
<h2 class="card__name" data-name>Margin Review</h2>
</article>
<article class="card" data-tags="packaging" style="--wdth: 88; --wght: 520">
<p class="card__meta"><span class="card__tags"><span data-tag="packaging">Packaging</span></span><span class="card__year">2025</span></p>
<h2 class="card__name" data-name>Ambrel Tea</h2>
</article>
<article class="card" data-tags="identity motion" style="--wdth: 125; --wght: 860">
<p class="card__meta"><span class="card__tags"><span data-tag="identity">Identity</span> · <span data-tag="motion">Motion</span></span><span class="card__year">2026</span></p>
<h2 class="card__name" data-name>Volta Week</h2>
</article>
<article class="card" data-tags="editorial" style="--wdth: 72; --wght: 380">
<p class="card__meta"><span class="card__tags"><span data-tag="editorial">Editorial</span></span><span class="card__year">2024</span></p>
<h2 class="card__name" data-name>North Ledger</h2>
</article>
<article class="card" data-tags="motion identity" style="--wdth: 100; --wght: 200">
<p class="card__meta"><span class="card__tags"><span data-tag="motion">Motion</span> · <span data-tag="identity">Identity</span></span><span class="card__year">2025</span></p>
<h2 class="card__name" data-name>Orrery</h2>
</article>
</section>
</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.
59 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 «Le schede coi segni di taglio» da Animorio e adattala al mio sitoUn solo path SVG sopra la riga dei filtri, ridisegnato a ogni fotogramma: per ogni angolo una riga orizzontale e una verticale che prolungano i lati della scheda, lunghe MARK[0] e staccate dall’angolo di MARK[1] pixel, sulle mezze coordinate e con shape-rendering crispEdges, così restano di un pixel netto.
Ogni angolo è un punto con posizione e velocità, tirato da una molla verso l’angolo della scheda scelta (offsetLeft, offsetTop, offsetWidth e offsetHeight, letti a ogni passo). Rigidità STIFFNESS e smorzamento DAMPING, diversi per ogni angolo di SPREAD; si integra sul ticker di GSAP in quattro sotto-passi, col passo limitato a 1/30 di secondo, e quando tutti e quattro sono fermi il ticker li lascia andare.
Gli angoli dal lato della scheda nuova partono subito, gli altri dopo STAGGER secondi l’uno, con gsap.delayedCall: in viaggio la cornice si allunga verso la scheda nuova e poi si richiude. La velocità apre i segni di qualche pixel e allunga le righe orizzontali; quando i quattro arrivano una molla piccola sulla distanza dall’angolo dà un colpo verso dentro, lo scatto a registro.
Ogni filtro ha sotto la parola una copia invisibile al peso più alto: la scheda è sempre larga quanto la sua parola scelta, così il peso che cresce non sposta le altre. Il peso è un numero scritto in font-variation-settings, con wght e un filo di wdth: sale oltre WEIGHT[1] di 40 e torna.
Prima del cambio si misura dove si vede ogni cornice (getBoundingClientRect, trasformazioni comprese), poi si cambia il filtro, si misura il posto nuovo e ogni cornice che resta parte con x e y dalla differenza e scivola a zero in CARDS secondi. Quelle che escono vengono tolte dalla griglia con position absolute dove si vedevano e svaniscono dietro le altre; la griglia tiene l’altezza di tutti i progetti, così quello che c’è sotto non si muove.
È un tablist vero: role tab e tabpanel, aria-selected, una sola scheda raggiungibile col tasto Tab; le frecce, Home e End cambiano filtro e portano il focus. Su uno schermo stretto i filtri si stringono con l’asse wdth per stare in una riga.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
MARK | script.js | [10, 5] | I segni di taglio: quanto è lunga ogni riga e quanto sta lontana dall’angolo, in pixel. |
STIFFNESS | script.js | 210 | Quanto sono rapidi i segni (la rigidità delle molle). |
DAMPING | script.js | 0.8 | Lo smorzamento delle molle: con 1 arrivano senza passare, più basso passano di più. |
SPREAD | script.js | 0.3 | Quanto sono diverse le quattro molle fra loro (0 = tutte uguali). |
STAGGER | script.js | 0.05 | I secondi fra la partenza di un angolo e quella del successivo. |
PULL | script.js | 4 | Quanto si sporgono i segni verso un filtro sotto il mouse, in pixel. |
WEIGHT | script.js | [360, 660] | Il peso dei filtri e quello del filtro scelto. |
CARDS | script.js | 0.75 | I secondi in cui i progetti scivolano al loro posto nuovo. |
Per i filtri dei lavori di uno studio, di un fotografo o di un’agenzia, o per le categorie di un catalogo e di un blog: da tre a sei parole brevi sopra una griglia. Il segno di taglio parla di stampa e di grafica, quindi sta bene soprattutto nei siti di chi fa immagini.
I filtri si stringono con l’asse wdth del carattere e stanno tutti in una riga; se non ci stessero la riga scorre di lato e porta in vista quello scelto. La griglia passa a due colonne. Il tocco fa come il clic e, premendo, i segni si stringono sulla parola come col mouse.
I segni di taglio svaniscono e ricompaiono già attorno alla scheda nuova, senza viaggiare; la griglia cambia con una dissolvenza, senza scivolare, e all’apertura tutto è già al suo posto.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 9,1 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.