Vai al contenuto
animorio
EN
Tutti i componenti

Il contatore che prende peso

Contatori, Testo, FisicaGSAPImpegnativaPeso compresso: Demo 11 KBGSAP 28 KBGratisScarica lo zip

Nello stile minimal: quanti ospiti per un tavolo, da 1 a 12, con un meno, un più e una cifra grande che a ogni ospite in più prende peso e un po’ di larghezza. La cifra nuova cade al suo posto, atterra un pixel troppo in basso e torna su, e la riga sottile sotto sente il colpo: vibra come una corda e si assesta. Dalla riga pendono dodici tacche, rosse fino al numero.

Il codice

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 stepper that gains weight</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">
    <!-- how many guests for a table: minus, the number, plus. Every guest more makes the number heavier and a little
         wider; the new number falls into its place, lands a pixel too low and the thin line under it feels the knock.
         Under the line, one thin tick per seat. The numbers, the line and the ticks are made by the script -->
    <div class="party" data-party>
      <p class="party__label" id="party-label">Guests</p>

      <div class="party__row">
        <button class="party__btn" type="button" aria-label="Remove a guest" data-less>
          <span class="party__btn-in" aria-hidden="true">
            <svg viewBox="0 0 48 48">
              <circle class="party__ring" cx="24" cy="24" r="23"/>
              <circle class="party__draw" cx="24" cy="24" r="23" pathLength="1"/>
              <path class="party__icon" d="M17 24h14"/>
            </svg>
          </span>
        </button>

        <div class="party__value" role="spinbutton" tabindex="0" aria-labelledby="party-label" aria-describedby="party-note" aria-valuemin="1" aria-valuemax="12" aria-valuenow="2" aria-valuetext="2 guests" data-value>
          <span class="party__window" aria-hidden="true" data-window></span>
        </div>

        <button class="party__btn" type="button" aria-label="Add a guest" data-more data-autoclic>
          <span class="party__btn-in" aria-hidden="true">
            <svg viewBox="0 0 48 48">
              <circle class="party__ring" cx="24" cy="24" r="23"/>
              <circle class="party__draw" cx="24" cy="24" r="23" pathLength="1"/>
              <path class="party__icon" d="M17 24h14M24 17v14"/>
            </svg>
          </span>
        </button>
      </div>

      <svg class="party__ruler" aria-hidden="true" data-ruler>
        <path class="party__rule" data-rule d=""/>
        <g data-ticks></g>
      </svg>

      <p class="party__note" id="party-note" data-note></p>
      <p class="sr" aria-live="polite" data-said></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>

Playground

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.

27 valori da cambiare

Oppure chiedila a Claude Code

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 contatore che prende peso» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco, in alto a sinistra la parola GUESTS in piccolo e in grigio; sotto, un meno e un più dentro due anelli sottilissimi e, in mezzo, il numero degli ospiti, enorme, in un carattere senza grazie a larghezza variabile. Sotto il numero una riga nera sottile da un capo all’altro, e dalla riga pendono dodici tacche, una per posto: quelle fino al numero sono vermiglio, le altre grigio chiaro. Sotto, in grigio, Tables seat up to 12. Il numero è il peso: a 1 ospite è sottilissimo e stretto, a 12 nerissimo e largo, e ogni ospite in più lo fa più spesso e un po’ più largo. Col più il numero vecchio sprofonda nella fessura appena sopra la riga e il nuovo cade dall’alto, accelerando, cifra dopo cifra; atterra un pixel più in basso del suo posto, si schiaccia appena e torna su, e proprio in quel momento prende il suo peso nuovo, andando un filo oltre e tornando indietro. La riga sente il colpo dove cade ogni cifra, più forte quanto più il numero è pesante: si piega, l’onda corre verso i due capi, rimbalza e si spegne, e le tacche appese la seguono. Intanto la tacca nuova si accende e si allunga con un piccolo elastico. Col meno il numero vecchio vola via verso l’alto sfumando e quello nuovo, più leggero, sale dalla fessura, va un pixel oltre e si posa; la riga, lasciata, dà un piccolo scatto in su. A 12 il più si spegne: premuto ancora, il numero scuote la testa, il suo peso spinge contro il limite e torna indietro, e la nota sotto diventa rossa, Our longest table seats 12; a 1 lo stesso col meno, At least one guest. Passando col mouse su un pulsante il suo anello si disegna dall’alto; premuto, il segno si fa più spesso. Tenendo premuto un pulsante il numero cambia di continuo, sempre più in fretta. Un tocco su una tacca porta il numero lì, e trascinando lungo la riga lo si sceglie; dalla tastiera il numero risponde alle frecce, a Pagina su e giù, a Home e a Fine.

Come funziona

Il numero è un peso

Le cifre sono in Archivo, un carattere variabile con due assi, peso (wght) e larghezza (wdth). Il conto non cambia gli assi direttamente: guida una molla smorzata (OMEGA 17, smorzamento 0,62 / SPRING) che va verso il conto nuovo, e il peso e la larghezza si leggono dalla posizione della molla, fra LIGHT e HEAVY. Così il peso cresce in un attimo, va un filo oltre e si assesta, e saltando da 3 a 12 con Fine si vede il numero gonfiarsi tutto in un colpo. Gli assi stanno su tutta la finestra, quindi il numero che arriva e quello che se ne va hanno sempre lo stesso peso.

La caduta e il pixel in più

Ogni numero è una riga di cifre (inline-block) in una finestra che sfuma in alto e taglia netto in basso, appena sopra la riga: quella è la fessura. Col più il numero vecchio sprofonda nella fessura in 0,12 secondi (power2.in) e il nuovo parte 0,09 secondi dopo da un terzo di cifra più in alto, così i due non si toccano mai; cade con power2.in, come una cosa lasciata andare, fino a 1,2 pixel sotto il suo posto, e torna su con elastic.out mentre tutto il numero si schiaccia del 2,5% sul fondo. Due cifre cadono una dopo l’altra, a 35 millesimi.

Una riga che è una corda

La riga è una corda di 56 pezzi con i capi fermi: a ogni passo (al massimo un millesimo di secondo, e un fotogramma lento conta per 1/30) ogni punto prende un’accelerazione dalla curvatura fra i due vicini, con un’onda che corre a 2600 pixel al secondo, e perde velocità per l’attrito. Una cifra che atterra dà alla corda una spinta a forma di campana proprio sotto il suo centro, misurato con getBoundingClientRect, e la spinta cresce col peso del numero: a 3 la riga si piega di un pixel e mezzo, saltando da 3 a 12 di più di quattro. Le tacche sono appese alla corda e si disegnano dove la corda passa. Quando corda e molla sono ferme il ciclo si toglie dal ticker di GSAP e non ridisegna.

Il no elastico

Al limite il numero non cambia: si sposta di 6 pixel verso il pulsante e torna con un elastic.out stretto, che fa due piccoli no; il segno del pulsante fa lo stesso di 3 pixel. La molla del peso riceve una spinta oltre il limite e ritorna, la corda un colpetto, e la nota sotto le tacche sale con la sua frase rossa e torna quella di sempre dopo 1,8 secondi.

Tasti, tocco e anteprima

Il numero è uno spinbutton con aria-valuenow e aria-valuetext, e una regione aria-live dice il conto mezzo secondo dopo l’ultimo cambio. Un pulsante conta alla pressione (pointerdown) e ripete tenendolo, con intervalli che si accorciano dell’80% fino a HOLD[2]; il clic che segue viene ignorato, mentre Invio e Spazio contano nel clic. La riga prende i tocchi e i trascinamenti (touch-action: pan-y, così la pagina scorre ancora). Il clic che arriva da uno script, quello dell’anteprima della libreria, fa invece un giro intero in una timeline GSAP: su fino a 12, un più di troppo, e giù fino al numero di partenza.

Valori da cambiare

NomeFileDi partenzaCosa cambia
MINscript.js1Il numero più piccolo di ospiti.
MAXscript.js12Il numero più grande di ospiti, che è anche il numero di tacche sulla riga (da 2 a 24).
STARTscript.js2Gli ospiti quando si apre la pagina.
LIGHTscript.js[140, 80]Il peso (da 100 a 900) e la larghezza (da 62 a 125) del numero col minimo degli ospiti.
HEAVYscript.js[860, 116]Il peso e la larghezza del numero col massimo degli ospiti.
DROPscript.js0.24Quanto ci mette un numero nuovo a cadere al suo posto, in secondi.
KNOCKscript.js1Quanto forte la riga sente un numero che atterra (0 = non si muove).
SPRINGscript.js1Quanto è elastico il peso: a 0,5 si posa senza oscillare, a 2 va oltre e ondeggia.
HOLDscript.js[0.42, 0.16, 0.06]Tenendo premuto un pulsante: dopo quanto comincia a ripetere, il primo intervallo e il più corto, in secondi.
WORDscript.js['guest', 'guests']La parola per uno e per più di uno, letta da chi usa un lettore di schermo.
NOTEscript.js['Tables seat up to {max}', 'Our longest table seats {max}', 'At least one guest']La nota sotto le tacche: a riposo, al massimo e al minimo; {max} diventa il numero più grande.

Provali nel Playground

Quando usarla

Per scegliere quante persone o quante cose quando il numero è piccolo e conta: gli ospiti di una prenotazione al ristorante, i posti di un tavolo, le persone di una visita guidata, le notti, i biglietti, le porzioni. Sta bene in un sito sobrio e tipografico, dove si vuole un gesto che si sente senza disegni intorno: il numero stesso dice quanto è grande il gruppo.

Sul telefono

Il numero si rimpicciolisce con la larghezza dello schermo (al massimo il 30% della sua larghezza), così a 390 pixel 12 nerissimo e largo sta fra i due pulsanti e niente sfora. Il dito fa come il mouse: un tocco su un pulsante conta uno e disegna l’anello, tenuto premuto ripete sempre più in fretta, un tocco su una tacca porta il numero lì e trascinando lungo la riga lo si sceglie, mentre lo scorrimento in verticale della pagina resta libero. Il tocco lungo non apre menu e due tocchi veloci non ingrandiscono la pagina.

Con il movimento ridotto

Niente cadute, rimbalzi, scossoni o corde che vibrano: il numero nuovo compare in dissolvenza al suo posto mentre il vecchio si dissolve, il peso cambia senza andare oltre, le tacche si accendono subito e la nota cambia con una dissolvenza. Tasti, pulsanti e riga funzionano come sempre.

Trappole

  • Il numero nuovo partiva da quasi mezza cifra più in alto mentre il vecchio sprofondava ancora: per qualche centesimo di secondo i due si sovrapponevano. Il vecchio ora scende in 0,12 secondi e il nuovo parte da un terzo di cifra, 0,09 secondi dopo: fatti i conti sulle due curve, la base del nuovo resta sempre sopra la cima del vecchio.
  • Il fondo della finestra taglia le cifre, ma la linea di base di un carattere non è il fondo della sua riga: con bottom: 0 le cifre sarebbero rimaste sospese sopra la riga di tutta la discendente, che cambia da un carattere all’altro. Lo script misura dove cade la linea di base con un inline-block alto zero (che si posa proprio lì) e la mette a 6 pixel dal fondo della finestra, anche quando cambia la misura.
  • Se gli assi fossero passati da un tween al numero che arriva, quello che se ne va sarebbe rimasto col peso vecchio e i due numeri, vicini, avrebbero avuto spessori diversi. Gli assi stanno sulla finestra e li guida una molla sola, che cambia meta quando il numero atterra.
  • Un clic col mouse arriva dopo pointerdown, che ha già contato: contava due volte. Il clic che segue una pressione si ignora, ma Invio e Spazio su un pulsante fanno solo il clic (con detail 0, come quello dell’anteprima): l’anteprima si riconosce perché il suo clic non è isTrusted.
  • Con il primo anello disegnato a riposo, lo stroke-dasharray lasciava un puntino in cima ai pulsanti anche a dashoffset 1: a riposo l’anello disegnato ha anche opacità zero.
  • Il riquadro della messa a fuoco intorno a tutto il numero tagliava la parola GUESTS, che sta nella parte alta e vuota della finestra: il riquadro comincia a un terzo della finestra e stringe le sole cifre.

Librerie

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 11 KB; le librerie: GSAP 28 KB.

Collaudo

Provata il 16 ottobre 2026

  • Computer: Fatto
  • Telefono: Fatto
  • Movimento ridotto: Fatto
  • Safari su iPhone: Da fare

Licenza d’uso

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.

Tutti i componenti