
The loader that becomes a logo
Transitions, SVG, Text
NewFree
A minimal page change: on a click the page lifts off the table and turns out to be the top sheet of a pad, the sheets under it just fanned. A thumb riffles it sideways, very fast, and every sheet is a frame: the old headline sinks, the new title rises and gains weight. The pad stops with a small knock on the page marked by the red ribbon.
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 thumb riffle transition</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage" data-stage>
<!-- the pad: the two real pages are its top and its bottom sheet; the thin sheets in between are added by the script -->
<div class="deck" data-deck>
<div class="pan" data-pan>
<section class="sheet page page--a" data-page="a" aria-label="Notebooks">
<header class="bar" data-bar>
<span class="brand">Quire</span>
<nav class="nav" aria-label="Pages">
<a href="#notebooks" aria-current="page">Notebooks</a>
<a href="#archive" data-go="b">Archive</a>
</nav>
</header>
<div class="hero">
<p class="kicker" data-rise>Notebooks, sewn by hand</p>
<h1 class="big big--a" data-big>Blank pages.</h1>
<a class="go" href="#archive" data-go="b" data-autoclic data-rise>
<span class="go__text">Open the archive</span>
<span class="go__arrow" aria-hidden="true"><span class="go__shaft"></span><svg class="go__head" viewBox="0 0 8 12"><path d="M1.5 1.5 6.5 6l-5 4.5"/></svg></span>
</a>
</div>
<footer class="foot" data-foot>
<span>Bound in small runs</span>
<span>Since 2011</span>
</footer>
<span class="sheet__shade" aria-hidden="true"></span>
</section>
<section class="sheet page page--b" data-page="b" aria-label="Archive" aria-hidden="true">
<header class="bar" data-bar>
<span class="brand">Quire</span>
<nav class="nav" aria-label="Pages">
<a href="#notebooks" data-go="a">Notebooks</a>
<a href="#archive" aria-current="page">Archive</a>
</nav>
</header>
<div class="hero">
<h2 class="big big--b" data-big>Archive</h2>
<div class="below">
<p class="lede" data-rise>Every notebook we have bound since the first one, kept on a shelf and still open to read.</p>
<a class="go go--back" href="#notebooks" data-go="a" data-autoclic data-rise>
<span class="go__arrow" aria-hidden="true"><svg class="go__head" viewBox="0 0 8 12"><path d="M6.5 1.5 1.5 6l5 4.5"/></svg><span class="go__shaft"></span></span>
<span class="go__text">Back to notebooks</span>
</a>
</div>
</div>
<footer class="foot" data-foot>
<span>Open on Saturdays</span>
<span>Since 2011</span>
</footer>
<!-- the ribbon marker: it hangs out of the pad at the page the thumb will stop on -->
<span class="ribbon" data-ribbon aria-hidden="true"></span>
<span class="sheet__shade" aria-hidden="true"></span>
</section>
</div>
</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.
28 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 thumb riffle transition” from Animorio and fit it into my siteThe two pages are the first and the last sheet of a stack of elements one on top of the other, each as big as the screen, with a falling z-index. The script adds SHEETS fake sheets in between and three sheets under the last page, the rest of the pad. Every sheet has a one-pixel edge made with box-shadow: 0 0 0 1px, which does not change its size. When the pad fills the screen the sheets all sit at zero and only the first one shows.
Sheet k is frame f = k / (SHEETS + 1). Its colour is a mix of paper and black in proportion f, and the type turns from dark to light halfway. The letters of the old headline are pushed down by q² × 1.3 em and lightened, the letters of the new title come up from below with a back.out curve worked out by hand (they overshoot by a hair) and go from 130 to 600 in weight. Every letter has its own delay, so the words come apart and together from left to right. The letters sit in a mask with overflow: hidden, so they vanish below the line.
The pad shrinks to LIFT and the sheets move i × SPREAD pixels to the right and a little less down, with half a pixel of untidiness. Then every sheet turns around its left edge to rotateY(90°), edge-on, with a transformPerspective of 1.4 times the width and a shade that darkens as it turns; at 90 degrees it is hidden. The starts are spread over RIFFLE seconds with a curve that slows just a little towards the end. The sheets' container follows the sum of the rotations, so the top sheet stays where the page was.
When the last sheet has gone, the pad squashes by 1.4% in 0.07 seconds and comes back with elastic.out(1, 0.35); the sheets underneath close in on the top one and spread again with an elastic, and the ribbon is kicked sideways and swings with elastic.out(1, 0.2). The ribbon lives inside the second page, hanging under its edge: with the pad filling the screen it stays off stage, and when the pad lifts it comes out by itself and marks where the thumb will stop. KNOCK sets the strength of the whole knock.
Each change is one timeline with the labels lift, catch, riffle, knock and close, and timeScale for SPEED. The sheets' starts are worked out as numbers, not as nested labels. A click that comes while the pad is being riffled waits in a queue. Both titles fit the width of the screen and the sheets' offset gets smaller on narrow screens. With reduced motion the sheets in between are never seen and the two pages swap with a fade.
| Name | File | Default | What it changes |
|---|---|---|---|
SHEETS | script.js | 12 | How many sheets sit between the two pages: each is a frame of the flip book. More sheets, a denser riffle and a smoother title. |
RIFFLE | script.js | 0.8 | The seconds the thumb takes to run through the whole pad. |
LIFT | script.js | 0.84 | How big the pad stays while it is riffled: 1 = it never leaves the screen. |
SPREAD | script.js | 3 | How many pixels each sheet sticks out from the one above: the fanned edge of the pad. 0 = even sheets. |
KNOCK | script.js | 1 | How hard the pad knocks when it stops: 0 = it just stops, 2 = a firm knock. |
SPEED | script.js | 1 | The speed of everything: 2 is twice as fast, 0.5 half as fast. |
To move from one page to another on a site about paper and books: a publisher, a magazine, a stationery shop or a bindery, an illustrator's portfolio, a newspaper archive, the step from a list to a book's page. It works well between a light page and a dark one.
The same riffle with the sizes adapted: the pad becomes a tall narrow notebook, the sheets stick out a little less and the titles shrink to fit the width of the screen. A tap on the link riffles it and riffles it back.
Nothing moves and nothing turns: the sheets in between are never seen, the first page fades out with the second already under it, title in place, then the text and the link fade in; going back the first page fades back in.
GSAP 3.15.0, Fraunces (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 8.6 KB; the libraries: GSAP 28 KB.
Tested on 14 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.