
Standing letters with a long shadow
Text, Scroll, 3D
NewFree
Scroll inside the preview
A short note typed as you scroll, in the minimal style: a thin ruler with a red mark that steps one column at every key, letters that fall light and gain weight as they land, and at the end of each line the carriage springing back while the paper rises by one line.
A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN. The React and Vue tabs hold the same demo as a ready component, which switches its animations off when it leaves the page.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The line typed on the ruler</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/martian-mono@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a short note of a made-up small press, typed as you scroll: a thin ruler with a red carriage mark that steps one
column at a time; at every step a letter is struck onto the line and gains weight as it lands; at the end of a
line the carriage springs back to the margin and the paper rises by one line. The lines are in LINES, at the top
of script.js -->
<main>
<section class="racconto" data-racconto>
<div class="palco" data-palco>
<header class="testa">
<p class="marchio">Pica</p>
<p class="piccolo">A note on writing</p>
</header>
<!-- the whole note for screen readers; the script writes it here and strikes the letters on their own layer -->
<p class="nota" data-nota></p>
<div class="macchina" aria-hidden="true">
<div class="carta" data-carta></div>
<div class="righello" data-righello>
<span class="righello__linea" data-linea></span>
<span class="carrello" data-carrello><span class="carrello__segno" data-segno></span></span>
</div>
</div>
<p class="piccolo invito" data-invito>Scroll to type</p>
</div>
</section>
<section class="coda">
<p class="coda__testo">Pica is a small press<br>for slow writing.</p>
<p class="piccolo">Notes, 2026</p>
</section>
</main>
<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>Change values, colours and text with the controls and watch the animation respond live. Or write in the code yourself. Then download the folder with your changes.
19 values to change
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The line typed on the ruler” from Animorio and fit it into my siteThe note lives in LINES, one string per line. The face is monospaced and variable (Martian Mono, with weight and width axes), so every letter has its own column: the script makes one element per letter, one column wide, and measures with a canvas how wide a figure is, to get the column from the width of the screen (and, if needed, from its height). The ruler has one column more than the longest line: that is where the carriage stops.
Every key (letter, space, carriage return) has its share of the scroll: a return is worth almost two. A ScrollTrigger without scrub reads how far the section has gone and works out how many keys should be struck. There is no timeline dragged by the scroll: a dragged elastic would stop halfway when the reader stops, with a letter still narrow or the carriage between two columns.
A small queue plays one key at a time towards the one the scroll asks for, never faster than PACE seconds per key, with gsap.delayedCall (so it stays in GSAP’s time). If the scroll runs too far ahead, the extra keys go in at once and the last six are still played; scrolling back, the queue runs backwards and lifts the letters off.
A letter starts at yPercent -DROP, NARROW wide and LIGHT in weight, and falls with power3.in. As it lands it squashes with scaleX and scaleY and takes its weight and width with elastic.out: the axes go through two CSS variables inside font-variation-settings, which GSAP tweens as numbers. Meanwhile the tick below jumps (an inner element, since the outer one belongs to the entrance), the mark stretches and the letter before dips by 1.2 pixels and comes back.
The carriage is a number in columns: one function draws it together with the paper and the tremor of the ruler, so it holds when the window is resized. On the return it runs to -0.14 columns with power3.in, the ticks lift at the exact moment the mark passes over them (the inverse of the cubic curve), then elastic.out with SPRING brings it back to zero, the ruler trembles by two pixels and the paper rises by one line with back.out.
| Name | File | Default | What it changes |
|---|---|---|---|
LINES | script.js | ['Write slowly.', 'Read it twice.', 'Keep it short.'] | The note, one string per line. Short lines work best, up to about twenty letters: the column narrows by itself to fit the screen. |
LIGHT | script.js | 130 | The weight of a letter while it falls. |
WEIGHT | script.js | 560 | The weight the letter settles on. |
NARROW | script.js | 75 | How narrow a letter is while it falls (the width axis, 75 to 100). |
DROP | script.js | 70 | How high a letter falls from, in percent of a line. |
PACE | script.js | 0.11 | The top speed when the scroll runs ahead, in seconds per key. |
SPRING | script.js | 0.35 | How loose the carriage is when it hits the margin: higher, more it swings. |
For the page of someone who writes (a small press, a newsletter, a blog), a studio’s short manifesto, the opening of an article, the welcome line of a site that wants to feel handmade. It works with two to four short lines.
The same: the column narrows to the width of the screen, and the letters, the ruler and the blows are the same.
No falling, no carriage and no rising paper: the note is already in its place above the ruler at full weight with its red full stop, and the letters fade in one after another as you scroll.
GSAP 3.15.0, ScrollTrigger (GSAP) 3.15.0, Martian Mono (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.4 KB; the libraries: GSAP + ScrollTrigger 45 KB.
Tested on 15 October 2026
Use it in your own projects and in your clients’ projects. Do not resell it or redistribute it as is. GSAP stays under its own Standard license. Full license.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.