
Lettere in piedi con l'ombra lunga
Testo, Scroll, 3D
NuovaGratis
Scorri dentro l’anteprima
Un fumetto in quattro tavole incise. Quando una didascalia arriva sullo schermo il suo riquadro si srotola dal bordo sinistro e le righe entrano una dopo l’altra; poi un narratore la legge, una parola rossa alla volta, al passo di una voce vera, e aspetta se scorri in fretta.
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>Captions that read aloud</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/im-fell-english@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/im-fell-english@5.3.0/400-italic.css">
<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>
<header class="bar">
<a class="brand" href="#">Tallow & Ink</a>
<nav class="bar__nav" aria-label="Sections">
<a href="#">Books</a>
<a href="#">Pre-order</a>
</nav>
</header>
<main>
<section class="intro">
<p class="kicker">A graphic novel in six chapters</p>
<h1 class="title" data-title>The Night Ferry</h1>
<p class="lede">Scroll down slowly. The narrator reads each caption as it arrives, and waits whenever you hurry.</p>
</section>
<!-- the story: four panels drawn by the script as engravings, each with its caption; a caption unrolls from its
left edge when it comes on screen, then the narrator reads it, one word at a time -->
<section class="strip" aria-label="Chapter one">
<figure class="panel panel--wide" data-panel="harbour">
<canvas class="panel__art" data-art aria-hidden="true"></canvas>
<figcaption class="caption caption--top" data-caption>Every night at eleven the last ferry leaves Corran harbour with its lamps lit and nobody aboard.</figcaption>
</figure>
<figure class="panel panel--right" data-panel="shore">
<canvas class="panel__art" data-art aria-hidden="true"></canvas>
<figcaption class="caption caption--bottom" data-caption>The ferryman counts the lights along the shore, one by one, until the fog has taken all of them.</figcaption>
</figure>
<figure class="panel panel--left" data-panel="bell">
<canvas class="panel__art" data-art aria-hidden="true"></canvas>
<figcaption class="caption caption--top caption--end" data-caption>Halfway across, a bell rings out where no buoy has ever been.</figcaption>
</figure>
<figure class="panel panel--wide" data-panel="answer">
<canvas class="panel__art" data-art aria-hidden="true"></canvas>
<figcaption class="caption caption--bottom" data-caption>He slows the engine and lifts his lantern. Far below, the water answers with a light of its own.</figcaption>
</figure>
</section>
<section class="end">
<p class="kicker">Chapter one is free to read</p>
<h2 class="end__title">Out on 14 November</h2>
<div class="end__actions">
<a class="button" href="#">Read chapter one</a>
<a class="button button--ghost" href="#">Pre-order the book</a>
</div>
</section>
</main>
<!-- the narrator: what it is doing, and the switch for a real voice where the browser has one -->
<aside class="narrator" data-narrator aria-live="off">
<span class="narrator__bars" aria-hidden="true"><i></i><i></i><i></i><i></i></span>
<span class="narrator__state" data-state>Narrator: quiet</span>
<button class="narrator__voice" type="button" data-voice aria-pressed="false" hidden>
<svg viewBox="0 0 20 20" width="16" height="16" aria-hidden="true"><path d="M3 7.5h3l4-3.5v12l-4-3.5H3z" fill="currentColor"/><path d="M13 7a4.2 4.2 0 0 1 0 6M15.4 4.8a7.4 7.4 0 0 1 0 10.4" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round"/></svg>
<span data-voice-label>Read aloud</span>
</button>
</aside>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.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.
41 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 «Le didascalie che leggono» da Animorio e adattala al mio sitoOgni scena è dipinta in grigi su tre tele nascoste: il tono, dal nero al bianco, l’angolo delle linee e quanto colore d’accento. Poi ogni pixel diventa inchiostro, carta o rosso confrontando il tono con un campo di linee ondulate distanti SPACING pixel, come nello shader del sito: sotto una prima soglia è inchiostro, sopra è il colore, sopra una seconda soglia è carta, e le linee spostano le due soglie, così i bordi delle ombre sono tratteggiati. Al buio metà di ogni linea è inchiostro, alla luce niente; in mezzo le linee si rompono in puntini.
Ogni tavola si incide tre volte, con un piccolo tremolio diverso nelle linee e una cornice storta in un altro modo, e i tre disegni si danno il cambio BOIL volte al secondo. Si preparano quando la tavola è a uno schermo di distanza, un disegno alla volta, per non fermare la pagina.
Quando il bordo alto della didascalia passa ENTER per cento dello schermo, il riquadro parte da FROM della sua larghezza e si srotola in UNROLL secondi con la curva cubic-bezier(0.45, 0.30, 0.16, 1) dell’originale, mentre tutta la didascalia arriva da SHIFT pixel a sinistra. Il riquadro si allarga con scaleX, il testo no: lo taglia un clip-path che segue il bordo del riquadro. Ogni riga entra dal bordo sinistro in SLIDE secondi (power3.out), STAGGER secondi dopo la precedente.
Ogni parola dura VOICE.perLetter secondi per lettera più VOICE.base, mai meno di VOICE.shortest; fra due parole passa VOICE.gap, dopo una virgola VOICE.comma, dopo un punto VOICE.stop. Sono le medie misurate sulle parole della voce narrante del sito. Una parola è rossa da LEAD secondi prima del suo inizio a LEAD dopo la sua fine, con uno smoothstep; PACE accelera o rallenta tutto.
Le didascalie che arrivano si mettono in coda. Il narratore prende la prima solo se non sta già leggendo e se la pagina è rimasta sotto CALM pixel al fotogramma per WAIT secondi. Una didascalia che esce dallo schermo lascia la coda, o sfuma in 0,4 secondi se era quella letta; con REPLAY si riavvolge e si rilegge quando torna.
Con «Read aloud» il narratore usa la sintesi vocale del browser. A ogni parola che la voce raggiunge (l’evento boundary) l’orologio delle parole si rimette su quella, così il rosso segue la voce anche se va a un altro passo; dove l’evento non arriva, il rosso segue i tempi calcolati.
| Nome | File | Di partenza | Cosa cambia |
|---|---|---|---|
UNROLL | script.js | 0.8 | I secondi che il riquadro impiega a srotolarsi dal bordo sinistro. |
FROM | script.js | 0.25 | Quanto del riquadro c’è già quando comincia a srotolarsi (da 0 a 1). |
SHIFT | script.js | 40 | Da quanti pixel a sinistra arriva tutta la didascalia. |
SLIDE | script.js | 2 | I secondi che ogni riga impiega a entrare dal bordo sinistro. |
STAGGER | script.js | 0.2 | I secondi fra una riga e la successiva (tre quarti oltre quattro righe). |
LEAD | script.js | 0.4 | I secondi in cui una parola diventa rossa prima di essere letta, e torna nera dopo. |
PACE | script.js | 1 | La velocità del narratore: 1 è il passo della voce registrata. |
CALM | script.js | 15 | La velocità di scorrimento, in pixel al fotogramma, sotto la quale il narratore può cominciare. |
WAIT | script.js | 0.1 | I secondi di scorrimento calmo prima che il narratore legga la didascalia seguente. |
ENTER | script.js | 62 | Dove arriva una didascalia: la sua altezza sullo schermo, dall’alto, in percentuale. |
REPLAY | script.js | true | Una didascalia uscita dallo schermo si riavvolge e si rilegge quando torna. |
BOIL | script.js | 8 | Quante volte al secondo le incisioni cambiano disegno. |
SPACING | script.js | 4.2 | La distanza fra le linee delle incisioni, in pixel. |
VOICE | script.js | { base: -0.036, perLetter: 0.076, shortest: 0.12, gap: 0.06, comma: 0.68, stop: 0.92, first: 0.23 } | I tempi della voce, in secondi: la durata di una parola per lettera (perLetter, più base, mai sotto shortest), la pausa fra le parole, dopo le virgole e dopo i punti, e l’attesa prima della prima parola. |
Per un racconto a pannelli: un fumetto, la storia di un marchio, una visita guidata, le didascalie di un video muto. Il narratore che aspetta funziona bene con didascalie brevi, di due o tre righe; le incisioni si possono sostituire con immagini vere senza toccare le didascalie.
Le tavole diventano verticali (4:5) e le didascalie più strette, con lo stesso narratore e la stessa voce. Lo scorrimento col dito conta come quello della rotella: una spinta veloce mette il narratore in attesa finché la pagina non rallenta.
Niente lettere che arrivano, niente riquadri che si srotolano e niente disegni che ribollono: le didascalie ci sono già e le tavole sono ferme. Il narratore legge lo stesso, perché il rosso che passa sulle parole cambia un colore, non muove niente.
GSAP 3.15.0, IM Fell English 5.3.0, Archivo (font variabile) 5.3.0.
Compressi con gzip, i tre file della demo pesano 16 KB; le librerie: GSAP + ScrollTrigger 45 KB.
Provata il 5 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.