
Il campo della password
Moduli, Testo, SVG
NuovaGratis
Nello stile minimal: la bio di un profilo, 160 caratteri, senza riquadro. Sotto il testo una linea sottile è lo spazio che resta: si accorcia a ogni lettera e finisce sul numero dei caratteri rimasti, in cifre tabellari che prendono peso man mano che il limite si avvicina senza mai cambiare larghezza. Oltre il limite le lettere in più sbiadiscono, un filetto arancio le barra una dopo l’altra, un segno dritto mostra dove cade il limite e il numero va sotto zero; cancellandole la linea esce di nuovo dal numero con una molla. Salvando, una linea più scura corre fino al numero e la pillola dice Saved.
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 field that counts its letters</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 short bio of a profile, 160 characters. No box round the field: its underline is the room that is left,
a hairline that gets shorter with every letter and ends at the count. Past the limit the extra letters are
struck through with a hairline of the accent and the count goes below zero; deleting them, the line grows
back on a spring. The marks over the text and the line are drawn by the script -->
<form class="bio is-waiting" action="#" novalidate data-bio data-autoclic>
<div class="bio__head">
<label class="bio__label" for="bio-text" data-label>Bio</label>
</div>
<div class="bio__box" data-box>
<div class="bio__mirror" aria-hidden="true" data-mirror></div>
<textarea class="bio__input" id="bio-text" name="bio" rows="3" maxlength="400" spellcheck="false" autocomplete="off" placeholder="A line or two about you" aria-describedby="bio-count bio-note" data-input>Type designer in Porto. I draw display faces for small presses and restore old wood type for anyone who still prints by hand.</textarea>
<svg class="bio__marks" aria-hidden="true" data-marks>
<path class="bio__wash" data-wash d=""/>
<path class="bio__strike" data-strike d=""/>
<path class="bio__limit" data-limit d=""/>
</svg>
<span class="bio__caret" aria-hidden="true" data-caret></span>
</div>
<div class="bio__gauge" data-gauge>
<svg class="bio__rule" aria-hidden="true" data-rule>
<path class="bio__track" data-track d=""/>
<path class="bio__line" data-line d=""/>
<path class="bio__ticks" data-ticks d=""/>
<path class="bio__run" data-run d=""/>
</svg>
<p class="bio__count" id="bio-count" data-count><span class="bio__num" aria-hidden="true" data-num>35</span><span class="sr" data-count-said>35 characters left</span></p>
</div>
<div class="bio__foot">
<p class="bio__note" id="bio-note" data-note><span class="note__line">Shown under your name on your profile.</span></p>
<button class="save" type="submit" data-save>
<span class="save__bg" aria-hidden="true"></span>
<span class="save__labels">
<span class="save__label is-on" data-word="save">Save</span>
<span class="save__label" aria-hidden="true" data-word="saving">Saving</span>
<span class="save__label" aria-hidden="true" data-word="saved">Saved</span>
</span>
</button>
</div>
<span class="sr" aria-live="polite" data-live></span>
</form>
</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.
26 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 campo che conta le lettere» da Animorio e adattala al mio sitoLa textarea è vera e disegna da sé lettere, cursore e selezione. Accanto, nascosto con visibility: hidden, c’è un div gemello con lo stesso carattere, la stessa larghezza, white-space: pre-wrap e overflow-wrap: break-word, che contiene lo stesso testo in un solo nodo. Per ogni carattere oltre il limite un Range sul gemello, con getClientRects, dà il riquadro della lettera nel suo rigo, anche dopo un a capo. I caratteri si contano come li conta l’occhio (codePointAt, così un emoji vale uno), e il limite si trasforma nella posizione giusta dentro il testo. Il gemello dice anche quanto è alto il testo: la textarea prende quell’altezza (niente barra di scorrimento) e il riquadro la segue con GSAP.
Sopra la textarea, in un SVG senza viewBox (un’unità è un pixel), tre tracciati riscritti a ogni fotogramma dai riquadri delle lettere: per ogni rigo un rettangolo del colore della pagina con opacità VEIL che sbiadisce le lettere in più, un filetto da 1,5 pixel all’altezza delle minuscole e un segno dritto dove cade il limite (fra due lettere, o a metà di uno spazio). Il filetto non salta da un rigo all’altro: una molla porta il numero delle lettere barrate verso quelle in più, e la lettera a metà è barrata per la parte che le tocca. Gli spazi a fine rigo restano fuori.
I due capi della riga, il peso del numero, il filetto, il segno e le piccole spinte delle tacche sono molle smorzate integrate a mano sul ticker di GSAP: accelerazione uguale a meno omega al quadrato per la distanza, meno due zeta omega per la velocità, col passo limitato a 1/30 di secondo e diviso in passi da 1/240. Quando la riga si accorcia la molla è quasi senza rimbalzo (zeta 0,86); quando si allunga vale GIVE, e quando le lettere in più se ne vanno il capo sinistro riceve una spinta di PUSH pixel al secondo verso sinistra, così la riga esce dal numero, va un poco oltre e si assesta. Il ciclo si addormenta quando tutte le molle sono ferme e nessun tween muove i colori.
Il numero è in Archivo con le cifre tabellari (tnum). Il peso va da LIGHT a HEAVY con una curva alla potenza CURVE della parte usata, così si sente soprattutto vicino al limite. Ma anche le cifre tabellari si allargano col peso: all’arrivo del carattere lo script misura dieci cifre a ogni peso, da 100 a 900 di 50 in 50, e cerca per bisezione la larghezza dell’asse wdth che le rende larghe come al peso più leggero. Durante il movimento wght e wdth cambiano insieme dalla tabella, e la fine della riga si sposta solo quando cambia il numero delle cifre. Sotto zero c’è il vero segno meno (U+2212, scritto con String.fromCharCode).
Save con la bio troppo lunga non salva: la pillola ha aria-disabled, il filetto si ispessisce con una molla e la frase sotto il campo diventa arancio. Con la bio giusta una riga da 2 pixel corre lungo tutta la misura in WAIT secondi; all’arrivo la tacca e il peso del numero ricevono una spinta, la pillola passa da Saving a Saved (tre parole nello stesso posto della griglia, così non cambia larghezza) e la regione aria-live lo dice. Cmd o Ctrl con Invio salva dalla tastiera. Un clic da script sul modulo (detail 0, l’anteprima della libreria) fa un giro intero in una timeline GSAP, senza prendere il fuoco e con un cursore disegnato: una frase aggiunta fino a sforare, una pausa sulle lettere barrate, la parte in più cancellata, Save, Saved e la bio com’era.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
LIMIT | script.js | 160 | Quanti caratteri può avere la bio. |
LIGHT | script.js | 220 | Il peso del numero quando c’è ancora tanto spazio. |
HEAVY | script.js | 820 | Il suo peso al limite e oltre. |
CURVE | script.js | 2.6 | Quanto tardi il numero prende peso: 1 piano piano dall’inizio, 4 solo nell’ultimo tratto. |
GIVE | script.js | 0.45 | Quanto è elastica la riga quando si riallunga: 0,25 rimbalza, 1 non rimbalza per niente. |
PUSH | script.js | 480 | La spinta che riceve la riga quando le lettere in più se ne vanno, in pixel al secondo. |
VEIL | script.js | 0.6 | Quanto sbiadiscono le lettere oltre il limite dietro al filetto, da 0 a 1. |
WAIT | script.js | 0.9 | Quanti secondi dura il salvataggio nella demo, mentre corre la riga più scura. |
DONE | script.js | Saved. Your profile shows it now. | La frase sotto il campo dopo il salvataggio. |
Dove si scrive un testo breve con un limite: la bio di un profilo, la descrizione di un negozio o di un evento, la didascalia di un post, il riassunto per i motori di ricerca, un messaggio per un biglietto regalo. La riga dice quanto spazio resta senza dover leggere il numero, e il filetto mostra esattamente quali lettere stanno fuori, invece di tagliarle senza avvisare come fa maxlength.
Il campo prende la larghezza dello schermo (358 pixel su un telefono di 390), il testo scende a 18 pixel su righe da 27, il numero a 20 e la pillola a 42. Il riquadro tiene posto per quattro righe, così la pagina non salta quando il testo va a capo; oltre, cresce con una molla. Un tocco apre la tastiera: ogni lettera accorcia la riga come col computer, e il filetto segue le lettere in più anche quando vanno a capo. La pillola si gonfia sotto il dito come col puntatore.
Niente molle: la riga, il peso del numero, il filetto e il segno del limite sono già al loro posto a ogni lettera, senza corse né rimbalzi. Cambiano in dissolvenza solo i colori, la riga sotto il campo e le parole della pillola, che si scambiano una dopo l’altra. Il salvataggio aspetta WAIT secondi senza la riga che corre, poi la pillola dice Saved.
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.