
The title that rises from a line
Transitions, Text, Images
NewFree
In the minimal style: a photo print comes into colour in three passes, like in a dye-sublimation printer. A thin head runs down the white card three times and leaves the yellow, then the magenta, then the cyan, each ink a few pixels out of register until it snaps into place; a last clear pass makes it shine.
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 photo in three passes</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/full.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage" data-stage>
<header class="top">
<p class="mark">Dyeline</p>
<p class="note">Proof</p>
</header>
<!-- a print card: a head runs down it three times, laying yellow, then magenta, then cyan, each ink a beat out
of register until it settles; a last clear pass makes it shine. Click for the next print -->
<section class="press" data-press>
<figure class="card" data-card role="img">
<div class="print" data-print>
<canvas class="ink" data-ink="y" aria-hidden="true"></canvas>
<canvas class="ink" data-ink="m" aria-hidden="true"></canvas>
<canvas class="ink" data-ink="c" aria-hidden="true"></canvas>
<div class="sheen" aria-hidden="true"><i class="sheen__band" data-band></i><i class="sheen__satin" data-satin></i></div>
<i class="head" data-head aria-hidden="true"></i>
</div>
</figure>
<ol class="passes" data-passes aria-hidden="true">
<li class="pass">Yellow</li>
<li class="pass">Magenta</li>
<li class="pass">Cyan</li>
<li class="pass">Coat</li>
</ol>
<p class="cap" data-cap aria-live="polite"><span class="cap__title" data-title></span><span class="cap__meta" data-meta></span></p>
</section>
</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.
23 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 photo in three passes” from Animorio and fit it into my siteThe script draws the photo on a canvas and makes three separations of it: yellow keeps only the blue channel (the other two at 255), magenta only the green, cyan only the red. They are three canvases stacked with mix-blend-mode: multiply over white: multiplied, they give back the exact photo.
Every ink has a number, r, from 0 to 1, saying how far it is printed: its canvas is cut with clip-path: inset(0 0 (1 − r) × 100% 0). The head is a two-pixel element that runs down on the same curve (sine.inOut) in the same time, so the edge of the ink is always exactly under it. The head is the colour it is printing.
Every ink starts a few pixels off (OFF_REGISTER, in different directions for magenta and cyan), and near the end of the pass goes back to zero with elastic.out: at the edges a thread of colour shows and snaps into place, like in progressive print proofs.
The last pass has a grey head and a band of white light in screen mode riding just above it; meanwhile a very light diagonal sheen grows and stays on the finished print, like the gloss of dye-sublimation prints.
Yellow, Magenta, Cyan and Coat are in Roboto Flex, a variable typeface with the wght and wdth axes. The word of the pass under way goes to weight 760 with elastic.out and narrows to width 92; the others go back to 300 and 118, grey. The whole sequence is one GSAP timeline per print.
| Name | File | Default | What it changes |
|---|---|---|---|
PRINTS | script.js | 3 stampe | The prints, one after the other: the title and the small line under the card (the script draws the photos). |
PASS | script.js | 1.25 | The seconds the head takes to run down the print. |
GAP_BETWEEN | script.js | 0.35 | The seconds between one pass and the next. |
OFF_REGISTER | script.js | 3 | How many pixels each ink lands out of register before it snaps into place (0 = always in register). |
HOLD | script.js | 2.2 | The seconds the finished print stays before the next one. |
For those who print or sell prints: an online photo lab, the page of a printing service for photos or postcards, the page of a limited-edition print, the moment an order 'goes to print'. Also as the loading of a photo in a portfolio.
The same animation with the sizes adapted: the card is almost as wide as the screen and the four words sit in a row underneath, smaller. A tap on the print moves on to the next.
Nothing runs down and nothing slides: the prints are already finished and one gives way to the next with a fade.
GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.8 KB; the libraries: GSAP 28 KB.
Tested on 19 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.