
The menu that opens from its button
Menus, Transitions, Text
Free
The pages of a list of results sit on a tape that runs through the bar, and the dots are its reels: changing page the tape runs, the numbers pass through the dark carriage of the current page and light up white, cut at its edge, the ones at the ends are wound narrow into the turning dots, and underneath the figures of the results roll.
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 tape pagination</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 pagination of a list of 472 results, ten to a page. The pages in between are numbers on a tape that runs
through the bar, and the two sets of dots are its reels: going to another page the tape runs, the numbers
slide through the dark carriage of the current page (lit white inside it), the ones at the ends are wound
into the dots and new ones come out of the other side. Under the bar the range of results rolls, digit by
digit. Without the script, the links below work as they are -->
<div class="pager" data-pager>
<nav class="bar" aria-label="Pagination" data-bar>
<a class="key key--prev" href="?page=6" rel="prev" aria-label="Previous page" data-prev>
<svg class="key__arrow" viewBox="0 0 24 24" aria-hidden="true"><path d="M14.25 6.5 8.75 12l5.5 5.5"/></svg>
</a>
<div class="track" data-track>
<ol class="slots" data-slots>
<li class="slot"><a class="slot__page" href="?page=1" aria-label="Page 1">1</a></li>
<li class="slot"><span class="slot__gap" aria-hidden="true">…</span></li>
<li class="slot"><a class="slot__page" href="?page=6" aria-label="Page 6">6</a></li>
<li class="slot"><a class="slot__page" href="?page=7" aria-label="Page 7" aria-current="page">7</a></li>
<li class="slot"><a class="slot__page" href="?page=8" aria-label="Page 8">8</a></li>
<li class="slot"><span class="slot__gap" aria-hidden="true">…</span></li>
<li class="slot"><a class="slot__page" href="?page=48" aria-label="Page 48">48</a></li>
</ol>
<!-- what the script draws: the carriage, the reels and the tape twice, the second one lit inside the carriage -->
<span class="carriage" aria-hidden="true" data-carriage></span>
<span class="reel" aria-hidden="true" data-reel><i></i><i></i><i></i></span>
<span class="reel" aria-hidden="true" data-reel><i></i><i></i><i></i></span>
<div class="tape" aria-hidden="true" data-tape></div>
<div class="tape tape--lit" aria-hidden="true" data-lit></div>
</div>
<a class="key key--next" href="?page=8" rel="next" aria-label="Next page" data-next data-autoclic>
<svg class="key__arrow" viewBox="0 0 24 24" aria-hidden="true"><path d="M9.75 6.5 15.25 12l-5.5 5.5"/></svg>
</a>
</nav>
<p class="range">
<span class="range__said" aria-live="polite" data-said>Results 61 to 70 of 472</span>
<span class="range__shown" aria-hidden="true"><span class="odo" data-odo>61</span><span class="range__dash">–</span><span class="odo" data-odo>70</span> of <span data-total>472</span> results</span>
</p>
</div>
</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.
24 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 tape pagination” from Animorio and fit it into my siteThe tape is not a series of states but a number: the page as a fraction, which GSAP takes from the old page to the new one. From it each frame works out u, the page in the middle slot, held back near the ends (between the fourth and the fourth from last with one neighbour each side), and the carriage's slot, m + page − u: in the middle it stays put and the numbers run, near the ends u stops and the carriage travels. A jump of forty pages runs them all through, and a click halfway starts again from where the tape has got to.
Each page has its place on the tape, r = m + p − u, held between the slots of the two sets of dots. How much of it shows is the smaller of r − eL and the last slot − r − eR, where eL and eR say how open the dots are (0 when the slot holds the second or the second to last page). So a page going into the dots narrows on the font's wdth axis down to 62, squashes and fades in the very slot where the dots are forming, and the classic rules of pagination (dots only when they hide at least two pages) come out on their own.
The tape is drawn twice, the same: the dark numbers and over them the white ones, clipped on every frame with a clip-path inset taken from the carriage's size, rounded corners included. So a number halfway is white inside and dark outside, cut at the edge. Both layers share the same glyphs: the numbers' weight grows with their closeness to the carriage in both, otherwise the two halves would not match. The carriage follows its slot on a spring, the tape drags it with its speed and it stretches when it runs.
Under the bar each number is a row of little windows, one per digit, each holding a column of figures written twice, so a window rolls on from 9 to 0 without going back. Each window goes to its new figure with the same duration and curve as the tape, and the leading digits that are not needed close up in width. A hidden aria-live region tells screen readers Results 71 to 80 of 472.
Under the tape are the real slots: links with href ?page=N and aria-label Page N, aria-current on the current page, the dots as buttons Ahead 5 pages, to page 12. Their text is transparent and the numbers you see are on the tape, aria-hidden; without the script the links show and work. The slots change at once, the tape catches up; the keyboard focus moves to the new current page. When nothing moves the loop stops drawing. The library's preview clicks page 1, the page after the current one, the dots and Next in turn: they have data-autoclic.
| Name | File | Default | What it changes |
|---|---|---|---|
RESULTS | script.js | 472 | How many results the list has. |
PER_PAGE | script.js | 10 | The results on each page. |
START | script.js | 7 | The page open when the component loads. |
NEIGHBOURS | script.js | 1 | The pages shown each side of the current one (fewer on a narrow screen, if they do not fit). |
SKIP | script.js | 5 | How many pages a click on the dots skips. |
STEP | script.js | 0.5 | The seconds the tape takes to move by one page (a far jump a little longer). |
FAR | script.js | 1.1 | The longest a jump can take, in seconds, however far it goes. |
TURN | script.js | 0.5 | How far the dots turn for each page wound into them, in turns (0.5: half a turn, and they are level again). |
SWAY | script.js | 1 | How far the tape drags the carriage before it springs back (0 not at all). |
SMEAR | script.js | 1 | How much the numbers smear when the tape runs fast (0 no trail). |
WIND | script.js | 0.16 | How far the reels wind up with the pointer on an arrow, in pages (0.16: a small turn). |
Under a long list split into pages: the results of a search, the orders of a shop, a blog's archive, a table in a dashboard. The tape shows where you are going and how far, even on a jump of forty pages, and the line underneath says at once which results are there.
The bar narrows to the screen with a 16 pixel margin each side (358 pixels on a 390 phone) and drops to 56 tall, with 40 pixel keys; each page is a target of about 34 by 44 pixels. If the chosen neighbours do not fit with slots of at least 34 pixels fewer are shown, and a long number that does not fit its slot narrows on the width axis. A finger on an arrow winds the reels up like the mouse, and a page held down shrinks on the tape.
The tape does not run: the numbers and the carriage fade out and back in already on the new page, the figures of the results swap with a fade, the dots do not turn. On arrival the component only fades in; no spring, no trail, no reels winding up.
GSAP 3.15.0, Archivo (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 12 KB; the libraries: GSAP 28 KB.
Tested on 6 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.