
Il menu che si apre dal pulsante
Menu, Transizioni, Testo
Gratis
Il banner dei cookie scritto come una frase sola, nello stile minimal: We use cookies for essentials, analytics and marketing. Le categorie sono parole della frase e interruttori veri: toccata, una parola viene barrata da una linea vermiglia sottile, perde peso e larghezza e salta sopra le altre fino in fondo alla frase, che si ricompone con FLIP («essentials only, not analytics or marketing»). Scelto, la frase si chiude in una riga e resta un piccolo link che dice cosa si è scelto.
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>Consent in one line</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>
<!-- the cookie banner written as one sentence, near the middle of the page (at the bottom on a real site). The kinds of cookies are words of the
sentence and real switches: struck with a thin line they move to the end («not analytics»), and the sentence
finds its new order. Once chosen, the sentence closes into a line, and a small link is left to open it again.
The words are made by script.js, from the values at its top -->
<div class="consent" data-consent>
<section class="banner" role="region" aria-label="Cookie consent" data-banner data-autoclic>
<span class="banner__frame" aria-hidden="true" data-frame></span>
<p class="sentence" data-sentence></p>
<div class="actions" data-actions>
<button class="pill pill--main" type="button" data-accept>
<span class="pill__bg" aria-hidden="true"></span>
<span class="pill__label" data-text="Accept all">Accept all</span>
</button>
<button class="pill" type="button" data-save>
<span class="pill__bg" aria-hidden="true"></span>
<span class="pill__label" data-text="Save choices">Save choices</span>
</button>
</div>
</section>
<button class="reopen" type="button" hidden data-reopen>
<span class="reopen__mask"><span class="reopen__text" data-reopen-text>Cookie settings <span class="reopen__state">· <span data-summary>all on</span></span></span></span>
<span class="reopen__line" aria-hidden="true" data-reopen-line></span>
</button>
<p class="sr" role="status" aria-live="polite" aria-atomic="true" data-live></p>
</div>
<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.
23 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 consenso in una riga» da Animorio e adattala al mio sitoLa frase si scrive da START, ALWAYS e KINDS a ogni cambio: le categorie accese con le virgole e and (con only se resta solo essentials), poi, se ce ne sono di spente, una virgola, not e le spente con or. Ogni pezzo è un elemento con una chiave: una categoria è sempre lo stesso pulsante (role switch, aria-checked), e passa da una parte all’altra della frase; una virgola o una parola di collegamento prende il nome della parola che viene dopo, così quando l’ordine cambia la vecchia sfuma e una nuova sale dove serve, e nessuna parola ne attraversa un’altra. Virgole e punto stanno dentro la parola che li precede: non si separano mai a fine riga.
Prima del cambio si misura ogni pezzo (getBoundingClientRect, transform compresi, così un cambio a metà riparte da dove le parole si trovano). Poi si rimette l’ordine nuovo, si dà a ogni parola il peso e la larghezza finali (wght 610 o 300, wdth 100 o 84) e si misura di nuovo. Ogni pezzo parte spostato della differenza e torna a zero con power3.inOut in RECOMPOSE secondi. Mentre viaggiano, ogni parola tiene la larghezza che avrà alla fine e il banner la sua nuova misura: la parola barrata dimagrisce per strada, e senza questo avrebbe trascinato le altre (sul telefono avrebbe anche spostato gli a capo).
La linea è uno span di 1,5 pixel dentro il testo della parola, sempre lungo quanto le lettere, all’altezza della metà delle minuscole, misurata con measureText: si disegna con scaleX da sinistra in STRIKE secondi e si stacca verso destra. La parola resta ferma mentre la linea corre, poi parte: sulla prima riga salta sopra le altre (HOP em in su con sine, e uno schiacciamento di 0,94 con elastic.out quando atterra); se cambia riga, o salterebbe nella riga di sopra, si piega piatta dove era e si riapre dove va con back.out, così non copre mai le altre parole.
La capsula è uno strato a sé, con left, top, width e height animati in pixel: segue la frase quando cambia lunghezza e, alla scelta, si chiude in un filo alto un pixel (bordo e ombra spariscono con una variabile CSS, --sh), diventa d’inchiostro e scende alla misura del link, mentre le parole si piegano con scaleY e l’asse wdth a 62. Il link sale dal filo dentro una maschera e il filo si consuma da tutte e due le parti. Riaprendo si fa lo stesso al contrario, e la capsula si apre con back.out, un pixel oltre e indietro.
Con Tab si va da essentials ad analytics e marketing (nell’ordine in cui la frase li dice in quel momento) e alle pillole; Spazio o Invio barrano e riaccendono, e la focalizzazione resta sulla parola anche dopo che si è spostata. Ogni cambio si annuncia in una regione aria-live con la frase nuova; chiudendo la focalizzazione passa al link, riaprendo alla prima categoria. Il clic dell’anteprima (detail 0) fa un giro in una timeline GSAP: barra marketing, poi analytics, riaccende analytics, salva, riapre, accetta tutto e riapre come all’inizio. Un tocco vero ferma il giro.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
START | script.js | 'We use cookies for' | Le parole prima delle categorie. |
ALWAYS | script.js | 'essentials' | La categoria sempre accesa, che non si può barrare. |
KINDS | script.js | ['analytics', 'marketing'] | Le categorie che si possono barrare, nell’ordine in cui la frase le dice. |
STRIKE | script.js | 0.34 | I secondi in cui la linea barra una parola, o se ne stacca. |
RECOMPOSE | script.js | 0.72 | I secondi in cui la frase trova il suo ordine nuovo. |
HOP | script.js | 0.85 | Quanto salta in alto la parola che passa sopra le altre, in em. |
CLOSE | script.js | 1 | Quanto lentamente il banner si chiude in una riga e si riapre (1 è la misura base). |
WEIGHTS | script.js | [330, 610, 300] | Il peso della frase, di una categoria accesa e di una barrata (da 100 a 900). |
STRUCK_WIDTH | script.js | 84 | La larghezza (asse wdth) di una parola barrata, da 62 a 125. |
Per il consenso ai cookie di un sito che vuole dirlo in poche parole, ma anche per ogni scelta che si legge come una frase: le notifiche che si ricevono (we’ll email you about orders and news), i dati che un’app condivide, gli ingredienti da togliere da un piatto.
La capsula prende tutta la larghezza meno dodici pixel per parte, la frase va a capo su due righe e le pillole stanno sotto, una accanto all’altra, metà per una. Le parole che cambiano riga si piegano e si riaprono invece di attraversare le altre; le stesse animazioni, solo misurate per il dito.
Niente salti, niente pieghe, niente fili che corrono: la linea compare già intera, la frase nuova appare con una dissolvenza al suo posto, il banner sfuma e al suo posto sfuma dentro il link, e lo stesso riaprendo.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 12 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.