
Il campo della password
Moduli, Testo, SVG
NuovaGratis
Il campo email di un’iscrizione battuto a macchina su una striscia di carta avvolta sul rullo: il punto di battuta resta fermo e a ogni tasto è la carta a spostarsi di uno scatto, mentre una leva sale dal basso e lascia la lettera inchiostrata in modo sempre un po’ diverso. Il tasto indietro toglie la lettera col nastro correttore, vicino al margine trema il campanello, e inviando la leva di ritorno riporta indietro il carrello, il rullo gira di una riga e la macchina scrive la risposta da sola.
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 typewriter field</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/courier-prime@5.3.0/400.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/courier-prime@5.3.0/400-italic.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/courier-prime@5.3.0/700.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the newsletter sign-up of a short fiction magazine, typed on a strip of paper wound on a black rubber platen:
the strike point stays still behind the metal guide and the paper moves, the return lever throws the carriage
back when the address is sent, the knurled knob turns with the platen and the bell shakes near the margin -->
<form class="tw" action="#" novalidate data-tw data-autoclic>
<div class="tw__top">
<label class="tw__label" for="tw-input">Email address</label>
</div>
<svg class="tw__bell" viewBox="0 0 28 22" aria-hidden="true" data-bell>
<g data-bell-body>
<path class="bell__dome" d="M8 16.2c0-4.6 2.6-7.6 6-7.6s6 3 6 7.6z"/>
<path class="bell__base" d="M6.4 16.6h15.2"/>
<path class="bell__stem" d="M14 8.6V6.4"/>
<circle class="bell__knob" cx="14" cy="5.4" r="1.4"/>
</g>
<path class="bell__ring" d="M5.4 8.2c-1.3 1.5-1.8 3.4-1.5 5.4M2.6 6.4C.8 8.6.1 11.3.6 14" data-ring/>
<path class="bell__ring" d="M22.6 8.2c1.3 1.5 1.8 3.4 1.5 5.4M25.4 6.4c1.8 2.2 2.5 4.9 2 7.6" data-ring/>
</svg>
<div class="tw__field" data-field>
<svg class="tw__lever" viewBox="0 0 34 40" aria-hidden="true" data-lever>
<defs>
<linearGradient id="tw-chrome" x1="0" y1="0" x2="1" y2="0.35">
<stop offset="0" stop-color="#8a8e95"/>
<stop offset="0.28" stop-color="#ffffff"/>
<stop offset="0.55" stop-color="#a4a8af"/>
<stop offset="0.78" stop-color="#e9ebee"/>
<stop offset="1" stop-color="#5d6168"/>
</linearGradient>
</defs>
<g data-lever-arm>
<path class="lever__arm" d="M12.4 34C12.3 25.6 9.8 17 5.2 10.2l3.6-2.4C13.4 14.8 17 24 17.6 34z"/>
<path class="lever__blade" d="M.9 8.8C.2 6.2 1.7 2.9 5 1.4 8.1 0 10.6.9 10.9 3c.3 1.9-1.2 3.9-3.3 5.3-2.4 1.6-5.9 2.6-6.7.5z"/>
<path class="lever__shine" d="M2.6 6.6c.9-1.9 2.6-3.3 4.7-3.8"/>
</g>
<circle class="lever__boss" cx="15" cy="34" r="4.4"/>
<circle class="lever__screw" cx="15" cy="34" r="1.3"/>
</svg>
<svg class="tw__knob" viewBox="0 0 16 50" preserveAspectRatio="none" aria-hidden="true">
<defs>
<linearGradient id="tw-knob" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#000" stop-opacity="0.85"/>
<stop offset="0.3" stop-color="#000" stop-opacity="0"/>
<stop offset="0.42" stop-color="#fff" stop-opacity="0.07"/>
<stop offset="0.7" stop-color="#000" stop-opacity="0"/>
<stop offset="1" stop-color="#000" stop-opacity="0.9"/>
</linearGradient>
</defs>
<rect class="knob__body" x="0" y="0" width="16" height="50" rx="4.5"/>
<path class="knob__ridges" data-ridges/>
<path class="knob__grooves" data-grooves/>
<rect x="0" y="0" width="16" height="50" rx="4.5" fill="url(#tw-knob)"/>
</svg>
<div class="tw__window" data-window>
<div class="tw__sheet" data-sheet>
<div class="tw__paper" data-paper></div>
<div class="tw__lines" aria-hidden="true" data-lines>
<span class="tw__ph" data-ph></span>
</div>
<input class="tw__input" id="tw-input" name="email" type="text" inputmode="email" autocomplete="email" autocapitalize="off" autocorrect="off" spellcheck="false" enterkeyhint="send" maxlength="254" aria-describedby="tw-help" aria-invalid="false" data-input>
</div>
<div class="tw__shade" aria-hidden="true"></div>
<div class="tw__guide" aria-hidden="true" data-guide>
<svg class="guide__plate" viewBox="-32 0 64 60">
<defs>
<linearGradient id="tw-plate" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#f6f7f8"/>
<stop offset="0.35" stop-color="#c3c7cd"/>
<stop offset="0.7" stop-color="#8b9098"/>
<stop offset="1" stop-color="#5c6067"/>
</linearGradient>
</defs>
<path class="guide__index" d="M-3.4 7.6h6.8L0 12.2z" data-index/>
<path class="guide__body" d="M-27 44.6c0-.9.7-1.6 1.6-1.6h21.6L0 47.4 3.8 43h21.6c.9 0 1.6.7 1.6 1.6v9.8H-27z"/>
<path class="guide__slots" d="M-15.5 46.6v4.6M15.5 46.6v4.6"/>
<path class="guide__lip" d="M-26 43.6h21.9M4.1 43.6H26"/>
</svg>
<span class="tw__tape" data-tape></span>
<span class="tw__bar" data-bar></span>
</div>
</div>
<button class="tw__key" type="submit" data-key>
<span class="key__top">
<span class="key__cap">
<span class="key__word" data-key-word>Subscribe</span>
<svg class="key__tick" viewBox="0 0 24 24" aria-hidden="true" data-key-tick><path d="M6.4 12.6l3.8 3.8 7.6-8.6"/></svg>
</span>
</span>
</button>
</div>
<div class="tw__help" aria-hidden="true" data-help><span class="help__line is-help">A new short story every other Sunday.</span></div>
<span class="sr" id="tw-help" data-help-sr></span>
<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.
24 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 a macchina da scrivere» da Animorio e adattala al mio sitoL’input è vero (label, autocomplete email, inputmode email per la tastiera con la @, enterkeyhint send, aria-invalid e aria-describedby verso una riga per i lettori di schermo, una regione aria-live per errori e risposta). Sta dentro il foglio che si sposta, largo migliaia di pixel così non scorre mai da sé, con le lettere trasparenti e il cursore visibile: le sue lettere cadono esattamente sotto quelle disegnate (un carattere monospaziato misurato con measureText), quindi il suo cursore, la selezione, l’autocompletamento e la tastiera del telefono funzionano dove si vedono.
A ogni cambio il valore si confronta col testo disegnato (stesso inizio, stessa fine). Quello che si aggiunge in fondo entra in una coda di battute, quello che si toglie in fondo in una coda di correzioni; ogni passo è una timeline di GSAP: il martelletto sale con power3.in, all’urto la lettera si inchiostra e il carrello avanza della sua larghezza, con un sobbalzo e un colpo del rullo che proseguono da soli. Se si accumulano passi la mano accelera fino a PASTE secondi a lettera. Un cambio in mezzo alla riga (la macchina non saprebbe farlo) scioglie la coda e le lettere si spostano al loro posto.
Una volta sola, su un canvas, si disegna un rumore a valori (macchie grandi quanto una lettera, una chiazzatura più fine, la trama obliqua del nastro e qualche fibra senza inchiostro) che diventa la maschera alfa di ogni lettera, presa da un punto diverso. Con mask-composite: intersect le si somma un gradiente con un angolo a caso, perché il martelletto non batte mai piatto. In più ogni lettera ha la sua densità, uno scarto sulla riga di JITTER pixel, un’inclinazione di TILT gradi e a volte una seconda battuta leggera in text-shadow; INK regola quanto è irregolare tutto.
Una riga sta sul cilindro del rullo: sale del raggio per il seno del suo angolo e si schiaccia del coseno, e si spegne girando via. Inviando, la leva ruota attorno al suo perno, il carrello corre al margine con power2.in e ci sbatte, e il rullo gira di una riga portando su l’indirizzo e giù la riga nuova; le scanalature della manopola, linee intorno a un cilindro visto di fronte, si ridisegnano solo mentre gira. Dopo l’attesa di subscribe() la risposta si batte da sola; un clic o un tasto fa girare il rullo al contrario.
Il controllo dice cosa manca e viene battuto sotto il campo lettera per lettera in rosso, con la stessa maschera d’inchiostro; il carrello trema e l’indice della guida diventa rosso. Quando il carrello passa BELL lettere prima del margine il campanello oscilla una volta per riga. Un clic da script sul modulo (detail 0, l’anteprima della libreria) batte da solo un indirizzo con un errore corretto, lo invia, poi uno senza finale, rifiutato in rosso, completato e inviato.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
PLACEHOLDER | script.js | 'you@example.com' | L’indirizzo scritto a matita sulla carta finché il campo è vuoto. |
DONE | script.js | 'You’re on the list.' | Quello che la macchina batte da sola sulla riga nuova quando l’indirizzo è partito. |
NOTE | script.js | 'The first story comes on Sunday.' | La riga battuta sotto il campo quando l’indirizzo è partito. |
STRIKE | script.js | 0.06 | I secondi che il martelletto impiega a salire e battere sulla carta. |
CARRIAGE | script.js | 0.07 | I secondi che il carrello impiega a scattare di uno spazio. |
JOLT | script.js | 1.2 | Di quanti pixel il carrello va oltre a ogni scatto (e quanto sobbalza il rullo). |
INK | script.js | 0.45 | Quanto è irregolare l’inchiostro: 0 tutte le lettere uguali, 1 macchiate e sbiadite. |
JITTER | script.js | 0.6 | Di quanti pixel una lettera può uscire dalla riga, in su o in giù. |
TILT | script.js | 0.6 | Di quanti gradi una lettera può pendere. |
PASTE | script.js | 0.035 | I secondi fra due battute quando un indirizzo intero è incollato o riempito dal browser. |
BELL | script.js | 6 | Quante lettere prima del margine oscilla il campanello. |
WAIT | script.js | 0.5 | Quanti secondi dura l’iscrizione nella demo, prima che la risposta venga battuta. |
Nell’iscrizione alla newsletter di una rivista, di uno scrittore, di una casa editrice, di una libreria o di un sito di racconti: dove lo scrivere è il prodotto e un campo qualsiasi sarebbe un’occasione persa. Resta un campo email vero, con l’autocompletamento del browser e la tastiera del telefono.
Su un telefono di 390 pixel il carrello è largo quanto lo schermo, resta alto 60, le lettere scendono a 16 pixel (così iOS non ingrandisce la pagina toccando il campo) e il tasto si stringe a 86. Un tocco apre la tastiera per le email col tasto Invio che dice Send; la carta, la leva e il campanello sono gli stessi, con meno lettere prima del margine.
Niente martelletto, niente scatti né sobbalzi: la carta si sposta subito di uno spazio e la lettera compare in dissolvenza al suo posto, e se ne va allo stesso modo. Inviando, la riga svanisce e la risposta compare lettera per lettera senza leva né rullo che gira; il carrello non trema, il campanello compare e svanisce fermo, le righe sotto il campo si scambiano in dissolvenza.
GSAP 3.15.0, Courier Prime 5.3.0.
Compressi con gzip, i tre file della demo pesano 18 KB; le librerie: GSAP 28 KB.
Provata il 7 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.