Skip to content
animorio
IT
Back to the library

The screensaver stool

Physics, TransitionsCanvas, GSAPMediumCompressed weight: Demo 11 KBGSAP 28 KBFreeDownload the zip

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.

The code

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>

Playground

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

Or ask Claude Code for it

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 site

What it does

The home page of an invented stool shop, Perch: the headline on the left, on the right the lilac shop window with the mustard stool and its price. At the bottom a tag counts the seconds: “Sit still. Screensaver in 4”, then 3, 2, 1. If nobody moves the mouse, presses a key, scrolls or touches the screen, a dark layer comes down over the page and the page under it stops being drawn. The stool leaves its window (which now says “Out for a walk”, with its shadow left behind) and crosses the dark in a straight line; at every wall it bounces with a small random swerve and changes colour: coral, mint, lilac, sky blue, mustard. If it touches two walls almost at once, in a corner, a copy of it stays printed in the dark and the line at the bottom says “Right in the corner.” At the first move the dark lifts, but the stool does not: it keeps flying over the page. You can catch it with the mouse or a finger: it follows the hand on a spring, a little late, and shrinks a touch when held. Thrown, it leaves with the speed of the hand and slows down bounce after bounce to its cruising speed. Brought gently against an edge, a “Let go to put it away” tag appears: let go there, it slides out through the edge and turns up in its window again, in its own colour. After a few quiet seconds the dark comes back and the stool sets off from where it is. The “Start it now” button starts everything at once.

How it works

The stool, once

The 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.

The countdown

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 flight

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.

In hand

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.

Off the edge

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.

Values to change

NameFileDefaultWhat it changes
IDLEscript.js4The seconds without a move, a key or a scroll before the screensaver starts. On a real site it would be a minute.
SPEEDscript.js205The stool’s cruising speed, in pixels per second.
SIZEscript.js0.42The stool’s height as a part of the screen (of its width, on a phone held upright). The shop window caps it.
SWERVEscript.js0.35How far each bounce bends the path at random, in radians: at 0 it is a perfect billiard, and the path repeats itself.
KEEPscript.js0.86How much of its speed a thrown stool keeps at each bounce, until it is back to SPEED.
THROWscript.js90, 520The slowest and the fastest throw, in pixels per second.
GRIPscript.js64, 11.5The spring that brings the stool to the hand: stiffness and damping. With less damping it wobbles more.
SQUEEZEscript.js0.95The stool’s size while it is held.
EDGEscript.js32How close to an edge the held stool must be to be put away, in pixels.
STILLscript.js160And how slowly it must be moving, in pixels per second: any faster is a throw.
FADEscript.js0.32The seconds the dark layer takes to come and to go.
NIGHTscript.js#1d1923The colour of the dark layer.
SHOPscript.js#f2b33dThe colour of the stool in the shop window.
COLORSscript.js#f2785c, #7ed3b2, #b9a2e8, #7fb8f0, #f2b33dThe colours it takes at the walls, one after the other.

Try them in the Playground

When to use it

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.

On phones

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”.

With reduced motion

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.

Pitfalls

  • The last two points of a path tell the last movement, not the pause: with the mouse still for half a second by the edge, the speed still came out at about 800 pixels per second and the tag never appeared. If the last point is older than the measuring window, the hand has no speed.
  • Some mice and trackpads can send mousemove even when still: counted as signs of life, they would wake the screensaver by themselves. A move counts from 4 pixels up.
  • An image’s box is bigger than the object: with it, the stool would bounce before touching. The solid part (alpha above 40) is measured once on a small copy.
  • The button that starts the screensaver is a sign of life itself: its click would wake it at once. After the click the script stops listening for 600 milliseconds.
  • On an iPhone a finger dragged over a full-screen page pulls it down and reloads it: while the stool is out the page has touch-action: none, and while it is held touchmove calls preventDefault.

Libraries

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.

Testing

Tested on 1 October 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: Done

License

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.

All animations