
Marquee that speeds up with scroll
Scroll, Text, Hover
Free
A book's contents with a thin thread between each title and its page, instead of dots: under the pointer the thread goes taut and short, pulls the number across to the title and the number counts like a counter from the page you were at to the chapter's page, then lights up; the title takes weight. Let go, the number goes back to the margin and the thread slackens with a twang. Minimal style.
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>Contents on a taut thread</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage" data-stage>
<header class="top">
<span class="top__name">Low Water</span>
<span class="top__note">Contents</span>
</header>
<!-- the contents: a title on the left, its page on the right, a hairline between them that hangs a little.
Under the pointer the line goes taut and short, pulling the page towards the title while it counts up to it -->
<nav class="toc" aria-label="Contents" data-toc></nav>
<p class="hint">Point at a chapter</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.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.
32 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 “Contents on a taut thread” from Animorio and fit it into my siteEach chapter is a link with display: grid: the title and the number sit in the same cell with align-items: baseline, so their baselines match, and the number moves only with transform: translateX from the left edge. The thread is an absolute svg as big as the row, with a single path. In front of the number there is a pad of hidden zeros: while it counts it stays as wide as its page, so at rest it sits flush with the margin and on its way it never jumps.
Every frame the path is M x0 y Q xm y+s x1 y: it starts just after the title (its width is read again because it changes with the weight) and ends just before the number. The middle point drops by s, the thread spring's slack times the length: a long thread hangs SAG pixels, a short one almost nothing. The thread runs at the height of the middle of the figures.
The number's position chases its goal (the margin, or the title plus GAP) on a nearly critical spring, NUMBER_SPRING, that goes a pixel past and comes back. The thread's slack chases zero when it is taut and SAG when it is slack, on a lightly damped spring, STRING_SPRING: that is why, let go, it twangs like a string. The springs are integrated by hand on GSAP's ticker in small steps of 1/240 of a second, steady at any screen rate.
The number is an object { v } carried by a GSAP tween, COUNT_TIME seconds on power2.out, from the page of the last chapter looked at to this one's, and written rounded every frame. At the end of the tween the row gets the is-set class and the number turns vermilion with a CSS transition. If you leave the chapter earlier, the count finishes quickly on its page while the number goes back.
A single pointermove on the window finds the row under the pointer from its band of height, as wide as the whole page: changing row lets the old one go and pulls the new one. Letting go and landing give a small kick to the slack speed of the threads next door, times NEIGHBOURS. A finger pulls the chapter it touches and leaves it pulled until it touches somewhere else; the links take the focus with Tab and do the same.
| Name | File | Default | What it changes |
|---|---|---|---|
CHAPTERS | script.js | [['Before the tide', 9], …] | The chapters: the title and the page, in the book's order. |
GAP | script.js | 68 | How close the number comes to its title, in pixels (the taut thread fills the space). |
SAG | script.js | 3 | How far a long thread hangs at rest, in pixels. |
NUMBER_SPRING | script.js | [230, 28] | The number's spring: how stiff, and how much it is held back. |
STRING_SPRING | script.js | [520, 7] | The thread's spring: how stiff, and how much it is held back (less holds, longer twang). |
WEIGHT | script.js | [320, 580] | The title's weight at rest and under the pointer (200 to 800). |
COUNT_TIME | script.js | 0.6 | The seconds the number takes to count up to its page. |
NEIGHBOURS | script.js | 0.5 | How much the threads next door feel a number landing or going back (0 to 1). |
For the contents of a book, an ebook or an online magazine, for the outline of a long article or guide, for the chapter list of a course: each entry with a number (page, minute, price) to tie to its title. It works with ten entries at most and titles that fit on one line; with long entries that wrap the thread has no room.
The same animations with the sizes adapted: the column is as wide as the screen, the titles smaller, the threads shorter and so hanging a little less. Touching a chapter the thread pulls it and leaves it pulled until you touch another chapter or somewhere else; dragging the finger goes from chapter to chapter. The hint at the bottom says Tap a chapter.
No springs, no twanging threads and no count: under the pointer the number appears already next to the title with a short fade, with the thread short and taut, and the title takes weight; leaving, the number fades back in on the margin. When the page opens everything fades in already in place.
GSAP 3.15.0, Newsreader (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.2 KB; the libraries: GSAP 28 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.