
La valutazione a stelle
Valutazioni, SVG, Hover
NuovaGratis
Il Log out di un'app come una pillola di cielo con un piccolo ritratto disegnato in SVG nella punta: sveglio, gli occhi seguono il puntatore e sbatte le palpebre a momenti casuali. Al clic le palpebre si fanno pesanti, uno sbadiglio, il cielo nella pillola scorre dal giorno al tramonto alla notte, il sole tramonta, sale la luna con poche stelle disegnate e il ritratto si addormenta con la testa piegata, respirando, mentre salgono piccole z disegnate: Signed out · Sleep well. Un altro clic lo sveglia di soprassalto e torna il sole: Good morning, Ada.
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 goodnight button</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the goodnight button: the Log out of an app, a pill of sky with a small drawn portrait in its round left end. The
portrait is awake: its eyes follow the pointer and it blinks now and then. A click logs out: the eyelids grow
heavy, a yawn, the sky inside the pill runs from day to night, the moon comes up and the portrait falls asleep
with its head on one side, breathing. Another click signs in: it wakes with a start and the sun comes back -->
<div class="night" data-night>
<button class="night__btn" type="button" data-btn data-autoclic>
<span class="night__fill" aria-hidden="true" data-fill>
<span class="night__sky" data-sky></span>
<span class="night__dark" data-dark></span>
</span>
<span class="night__clip" aria-hidden="true">
<svg class="night__heavens" viewBox="0 0 40 60" data-heavens>
<defs>
<mask id="nb-crescent">
<circle cx="20" cy="23" r="7.4" fill="#fff" />
<circle cx="23.6" cy="20" r="6.6" fill="#000" />
</mask>
</defs>
<g class="night__stars" data-stars>
<path transform="translate(5 12) scale(0.9)" d="M0 -2.4Q0.35 -0.35 2.4 0Q0.35 0.35 0 2.4Q-0.35 0.35 -2.4 0Q-0.35 -0.35 0 -2.4Z" />
<path transform="translate(34 42) scale(0.7)" d="M0 -2.4Q0.35 -0.35 2.4 0Q0.35 0.35 0 2.4Q-0.35 0.35 -2.4 0Q-0.35 -0.35 0 -2.4Z" />
<path transform="translate(9 46) scale(0.55)" d="M0 -2.4Q0.35 -0.35 2.4 0Q0.35 0.35 0 2.4Q-0.35 0.35 -2.4 0Q-0.35 -0.35 0 -2.4Z" />
<path transform="translate(33 8) scale(0.5)" d="M0 -2.4Q0.35 -0.35 2.4 0Q0.35 0.35 0 2.4Q-0.35 0.35 -2.4 0Q-0.35 -0.35 0 -2.4Z" />
</g>
<g data-sun>
<g class="night__rays" data-rays>
<path d="M20 12.2v-2.6M20 33.8v2.6M9.2 23h-2.6M30.8 23h2.6M12.4 15.4l-1.8-1.8M27.6 30.6l1.8 1.8M12.4 30.6l-1.8 1.8M27.6 15.4l1.8-1.8" />
</g>
<circle class="night__sun" cx="20" cy="23" r="7" />
</g>
<g data-moon>
<rect class="night__moon" x="10" y="13" width="20" height="20" mask="url(#nb-crescent)" />
</g>
</svg>
<svg class="night__zs" viewBox="0 0 14 21" data-zs>
<path d="M0 0h3.4L0 3.8h3.4" />
<path d="M0 0h3.4L0 3.8h3.4" />
<path d="M0 0h3.4L0 3.8h3.4" />
</svg>
</span>
<span class="night__portrait" aria-hidden="true">
<svg viewBox="0 0 50 50" data-portrait>
<defs>
<clipPath id="nb-round"><circle cx="25" cy="25" r="23.6" /></clipPath>
<clipPath id="nb-eye"><path d="M-2.7 0Q0 -2.7 2.7 0Q0 2.1 -2.7 0Z" /></clipPath>
</defs>
<g clip-path="url(#nb-round)">
<circle class="pt-back" cx="25" cy="25" r="24" />
<g data-body>
<path class="pt-sweater" d="M2 52C3 41.5 12.5 37.6 25 37.6S47 41.5 48 52Z" />
<path class="pt-neck" d="M21.3 30.5h7.4v6.6q-3.7 2.8 -7.4 0Z" />
<path class="pt-collar" d="M19.4 38.2Q25 43 30.6 38.2" />
</g>
<g data-head>
<path class="pt-hair" d="M12.2 26C11.2 14.2 17 8.6 25 8.6S38.8 14.2 37.8 26C37.6 31 36.4 33.8 34.6 34.6L15.4 34.6C13.6 33.8 12.4 31 12.2 26Z" />
<ellipse class="pt-skin" cx="15.2" cy="25.4" rx="1.8" ry="2.5" />
<ellipse class="pt-skin" cx="34.8" cy="25.4" rx="1.8" ry="2.5" />
<ellipse class="pt-skin" cx="25" cy="24.6" rx="9.7" ry="11.1" />
<g data-face>
<ellipse class="pt-cheek" cx="18.6" cy="28.6" rx="2" ry="1.2" />
<ellipse class="pt-cheek" cx="31.4" cy="28.6" rx="2" ry="1.2" />
<g class="pt-eye" transform="translate(21 24.6)">
<path class="pt-white" d="M-2.7 0Q0 -2.7 2.7 0Q0 2.1 -2.7 0Z" />
<g clip-path="url(#nb-eye)">
<g data-pupil>
<circle class="pt-iris" r="1.45" />
<circle class="pt-glint" cx="-0.45" cy="-0.5" r="0.42" />
</g>
<rect class="pt-lid" x="-3" y="-2.6" width="6" height="0" data-lid />
</g>
<path class="pt-lash" d="M-2.8 0Q0 -1.2 2.8 0" data-lash />
</g>
<g class="pt-eye" transform="translate(29 24.6)">
<path class="pt-white" d="M-2.7 0Q0 -2.7 2.7 0Q0 2.1 -2.7 0Z" />
<g clip-path="url(#nb-eye)">
<g data-pupil>
<circle class="pt-iris" r="1.45" />
<circle class="pt-glint" cx="-0.45" cy="-0.5" r="0.42" />
</g>
<rect class="pt-lid" x="-3" y="-2.6" width="6" height="0" data-lid />
</g>
<path class="pt-lash" d="M-2.8 0Q0 -1.2 2.8 0" data-lash />
</g>
<path class="pt-brow" d="M18.6 20.6Q21 19.4 23.2 20.4" data-brow />
<path class="pt-brow" d="M26.8 20.4Q29 19.4 31.4 20.6" data-brow />
<path class="pt-nose" d="M25.3 25.8Q26.2 27.6 24.9 28" />
<path class="pt-smile" d="M23 30.6Q25 32 27 30.6" data-smile />
<ellipse class="pt-yawn" cx="25" cy="31.2" rx="0" ry="0" data-yawn />
</g>
<path class="pt-hair" d="M14.8 23C14.6 14.6 19.6 11.4 25.6 11.4C31 11.4 35.4 14.4 35.6 22C32.6 18.4 28.6 16.6 24.2 17.4C20.4 18.2 17.2 20.2 14.8 23Z" data-fringe />
</g>
<rect class="pt-moonlight" x="0" y="0" width="50" height="50" data-moonlight />
</g>
<circle class="pt-ring" cx="25" cy="25" r="23.8" />
</svg>
</span>
<span class="night__label">
<span class="night__word" data-word data-wide="Log out">Log out</span>
</span>
</button>
<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.
30 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 pulsante della buonanotte» da Animorio e adattala al mio sitoIl ritratto è un SVG di 50 unità ritagliato in un cerchio: il maglione e il collo in un gruppo, la testa (capelli dietro, orecchie, viso, i lineamenti, la frangia davanti) in un altro che si piega intorno al collo. Ogni occhio è una mandorla bianca con dentro, ritagliate dalla stessa mandorla, la pupilla col suo riflesso e la palpebra: un rettangolo color pelle che cresce in altezza. Il bordo della palpebra è una curva sola che scende con lei e si rovescia: arcuata da aperta, la curva del sonno da chiusa.
Il viso è un oggetto di numeri (lo sguardo, le palpebre, l'ammiccare, il sorriso, lo sbadiglio, le sopracciglia, l'inclinazione, il sobbalzo, il respiro, la luce della luna) che GSAP anima e una funzione scrive nell'SVG: trasformazioni, l'altezza delle palpebre, i tracciati del bordo, delle sopracciglia e della bocca ricostruiti a ogni fotogramma. Una chiave fatta dei numeri arrotondati al centesimo dice se qualcosa è cambiato: se no, non si scrive niente e il ciclo si ferma.
La direzione dal centro del ritratto al puntatore, piena oltre 90 pixel e proporzionale più vicino, è la meta dello sguardo; lo sguardo disegnato la segue su una molla svelta (4,2 oscillazioni al secondo, smorzamento 0,62), così gli occhi scattano e si posano. Le pupille si spostano di 1,1 unità, i lineamenti di 0,9, la frangia di 0,45 e la testa gira di 1,2 gradi: la parallasse fra gli strati dà la profondità. LOOK le scala tutte.
Un delayedCall di GSAP richiama sé stesso a un momento casuale fra i due numeri di BLINK; l'ammiccare scende in 0,07 secondi e risale in 0,15, e una volta su cinque circa lo rifà subito. È un numero a parte dalle palpebre pesanti, e conta il più chiuso dei due, così un ammiccare non riapre gli occhi di chi ha sonno.
Il cielo è un gradiente alto quattro pillole (giorno, tramonto pesca, malva, notte) dentro il fondo con overflow: hidden; uscire lo fa salire di yPercent −75 in DUSK secondi, ed entrare lo riporta giù. Il sole scende di 60 unità, la luna (un rettangolo con una maschera a falce: un cerchio bianco meno uno nero spostato) sale al suo posto, le stelle a quattro punte entrano con back.out e restano ferme, il colore delle parole passa per una variabile CSS animata da GSAP e un velo blu sul ritratto fa la luce della luna.
Il pulsante è un button vero, con aria-disabled mentre esce o entra e una zona aria-live che dice Logging out…, Signed out · Sleep well, Signing in… e Good morning, Ada; tutto è simulato coi tempi di GSAP. Addormentato, il respiro è un tween in yoyo infinito e le z una timeline ripetuta di tre lettere disegnate; svegliandosi si fermano. La pillola prende la larghezza misurata delle parole con back.out lasciando a destra il posto del sole, e quando si stringe aspetta che le vecchie parole siano sparite.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
LOG_OUT | script.js | Log out | La scritta a riposo, da dentro. |
LOGGING_OUT | script.js | Logging out… | La scritta mentre esce; la dice anche la zona aria-live. |
SLEEP_WELL | script.js | Signed out · Sleep well | La scritta appena uscito, prima di Sign in. |
SIGN_IN | script.js | Sign in | La scritta a riposo, da fuori. |
SIGNING_IN | script.js | Signing in… | La scritta mentre entra. |
MORNING | script.js | Good morning, Ada | Il saluto appena entrato. L'accesso è simulato: in un sito vero qui va il nome che il tuo server restituisce. |
DUSK | script.js | 1.8 | I secondi in cui il cielo passa dal giorno alla notte. |
BLINK | script.js | [1.6, 4.8] | Fra quanti secondi, al minimo e al massimo, arriva il prossimo battito di palpebre. |
LOOK | script.js | 1 | Quanto gli occhi e il viso si girano verso il puntatore: 0 restano fermi. |
TILT | script.js | 13 | Quanto si piega la testa da un lato quando dorme, in gradi. |
BREATH | script.js | 3.4 | I secondi di un respiro nel sonno. |
Per l'uscita di un'app serale o tranquilla: sonno e meditazione, lettura, musica, un diario, un'app per bambini o per la famiglia, o semplicemente un prodotto con un tono gentile. Il ritratto va sostituito con l'avatar dell'utente o con la mascotte del prodotto; l'uscita vera va collegata al proprio server: qui è simulata.
La pillola è larga fra circa 190 e 300 pixel e a 390 ci sta sempre; se le parole sono troppo lunghe il carattere si rimpicciolisce. Gli occhi seguono il dito appoggiato sulla pagina, il tocco esce o entra; il ritratto, il sole e la luna restano della stessa misura.
Gli occhi non seguono il puntatore e non sbattono, niente sbadiglio, niente respiro né z, la pillola non si gonfia e la scritta non si allarga. Al clic il ritratto svanisce e ricompare già addormentato, la notte arriva in dissolvenza sopra il giorno, il sole svanisce e la luna e le stelle compaiono in dissolvenza; un altro clic fa tornare il giorno e il ritratto sveglio nello stesso modo.
GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 11 KB; le librerie: GSAP 28 KB.
Provata il 12 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.