
The cloth reveal transition
Transitions, Physics
NewFree
Left alone for a few seconds, the page goes dark under a quiet layer and the stool from the shop window bounces from edge to edge like the old DVD logo, changing colour at every wall. At the first move the dark lifts but the stool keeps flying over the page: catch it, throw it, and let go of it gently by an edge to send it back to its window.
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 screensaver stool</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/unbounded@5.3.0/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/dm-sans@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- the shop: an ordinary page, with the stool in its window -->
<main class="shop" data-shop>
<header class="bar">
<a class="brand" href="#">Perch</a>
<nav class="bar__nav" aria-label="Sections">
<a href="#">Stools</a>
<a href="#">Benches</a>
<a href="#">Journal</a>
</nav>
<a class="bar__bag" href="#">Bag (0)</a>
</header>
<section class="hero">
<div class="hero__words">
<h1 class="hero__title">Somewhere to land.</h1>
<p class="hero__line">Three legs, solid ash, light enough to carry in one hand. The Perch Three goes wherever the conversation goes.</p>
</div>
<!-- the window: the stool itself is drawn on the canvas below, which sits on this spot until it flies off -->
<figure class="window">
<div class="window__spot" data-spot role="img" aria-label="The Perch Three stool in mustard"></div>
<figcaption class="window__label">
<span data-label>Perch Three, mustard</span>
<span class="window__price">€140</span>
</figcaption>
</figure>
</section>
<footer class="foot">
<p class="chip" data-hint>
<span data-wait>Sit still. Screensaver in <span class="chip__count" data-count>4</span></span>
<span data-play hidden>Catch the stool and throw it. Let go of it by an edge to put it away.</span>
</p>
<button class="chip chip--button" type="button" data-start data-autoclic>Start it now</button>
</footer>
</main>
<!-- the quiet layer: when it is fully dark the page under it stops being drawn -->
<div class="quiet" data-quiet aria-hidden="true">
<div class="quiet__stamps" data-stamps></div>
<p class="quiet__note" data-note>Perch is resting. Move to wake it.</p>
</div>
<!-- the stool: one canvas, moved with a transform, repainted only when it changes colour -->
<canvas class="flyer" data-flyer aria-hidden="true"></canvas>
<p class="release" data-release aria-hidden="true">Let go to put it away</p>
<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.
39 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 screensaver stool” from Animorio and fit it into my siteThe stool is drawn in greys on a canvas as big as it is shown: the seat is an ellipse with its edge, the legs are bars that narrow towards the feet, lit from the left, and there is a footrest ring. For every colour a copy is made: the brightness of each pixel is read, stretched between the darkest and the lightest, and the pixel becomes that colour at 22% to 100%. The copies are kept, so a change of colour costs one drawImage. On a copy 160 pixels wide the script also measures where the stool is solid (alpha above 40): those edges, not the box’s, are the ones that touch the walls.
Every frame counts the seconds since the last sign of life: a mouse move of at least 4 pixels, a key, the wheel, a finger. After IDLE seconds the dark layer comes up in FADE seconds with GSAP, and once it is full the page under it gets visibility: hidden: the browser has nothing left to repaint. The count lives in the frame loop with performance.now, not in a setTimeout, so it stops when the tab is hidden and slows down in slow motion.
The stool leaves the window in a random direction and goes straight at SPEED pixels per second; all that moves it is a transform on a canvas, never a redraw. At a wall the direction bends at random by up to SWERVE radians, turns away from the wall, and the speed becomes the higher of SPEED and the old speed times KEEP: a stool thrown hard slows down bounce after bounce, a slow one picks up its pace. Neither component drops under a quarter of the speed, so the path never becomes a flat line that crosses the screen without visiting it. Two walls less than 120 milliseconds apart make a corner, and a copy stays there.
A click or a finger inside the solid part of the stool catches it. From then on a spring pulls it towards the hand every frame (GRIP: stiffness and damping), with a lag and a wobble you can just see, and a second spring squeezes it to SQUEEZE. On release, the speed of the throw is read from the last 40 milliseconds of the pointer’s path (or the last 90), and kept between the two THROW values. A hand that has been still for longer than that has no speed of its own: what counts is the stool’s, on its spring.
If the held stool is less than EDGE pixels from an edge and moving slower than STILL pixels per second, “Let go to put it away” appears next to the pointer. Let go there, it slides out through the nearest edge in 0.42 seconds, speeding up, then turns up in its window in its own colour and the countdown starts again.
| Name | File | Default | What it changes |
|---|---|---|---|
IDLE | script.js | 4 | The seconds without a move, a key or a scroll before the screensaver starts. On a real site it would be a minute. |
SPEED | script.js | 205 | The stool’s cruising speed, in pixels per second. |
SIZE | script.js | 0.42 | The stool’s height as a part of the screen (of its width, on a phone held upright). The shop window caps it. |
SWERVE | script.js | 0.35 | How far each bounce bends the path at random, in radians: at 0 it is a perfect billiard, and the path repeats itself. |
KEEP | script.js | 0.86 | How much of its speed a thrown stool keeps at each bounce, until it is back to SPEED. |
THROW | script.js | 90, 520 | The slowest and the fastest throw, in pixels per second. |
GRIP | script.js | 64, 11.5 | The spring that brings the stool to the hand: stiffness and damping. With less damping it wobbles more. |
SQUEEZE | script.js | 0.95 | The stool’s size while it is held. |
EDGE | script.js | 32 | How close to an edge the held stool must be to be put away, in pixels. |
STILL | script.js | 160 | And how slowly it must be moving, in pixels per second: any faster is a throw. |
FADE | script.js | 0.32 | The seconds the dark layer takes to come and to go. |
NIGHT | script.js | #1d1923 | The colour of the dark layer. |
SHOP | script.js | #f2b33d | The colour of the stool in the shop window. |
COLORS | script.js | #f2785c, #7ed3b2, #b9a2e8, #7fb8f0, #f2b33d | The colours it takes at the walls, one after the other. |
For the home page of a shop or a brand with a product worth looking at, cut out on a transparent background: a chair, a bottle, a shoe, a jar. It also works well on screens left on in a shop window or at a fair. It is wrong on a page meant for long reading, where readers sit still for minutes: there IDLE should be a minute, as on the original site, or the screensaver becomes an interruption.
It works with a finger: a touch brings the page back and the stool is dragged and thrown the same way. It is smaller, because its height comes from the screen’s width, and while it is out of its window the page does not scroll and cannot be pulled down to reload. The tag at the bottom says “Grab” instead of “Catch”.
No flight: in the dark the stool stands still in the middle and changes colour every 2.6 seconds, without moving. Any move brings the page back with the stool in its window, and there is nothing to catch.
GSAP 3.15.0, Unbounded (font variabile) 5.3.0, DM Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 11 KB; the libraries: GSAP 28 KB.
Tested on 1 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.