
The screensaver stool
Physics, Transitions
NewFree
A page change in the minimal style: a thin orange rule hung above the screen is let go and falls like a pendulum; everything it sweeps is already the new page, and the letters of the title lean as it passes. It swings past the upright, comes back, calms down and stops exactly where the new page has its column rule.
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 pendulum transition</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>
<!-- the first page: its column rule stands on the right -->
<section class="page page--a is-on" data-page="a" aria-label="Shop">
<span class="rule" aria-hidden="true"></span>
<header class="bar">
<span class="brand">Hollis</span>
<nav class="nav" aria-label="Pages">
<a href="#shop" aria-current="page">Shop</a>
<a href="#repairs" data-go="b">Repairs</a>
</nav>
</header>
<div class="main">
<h1 class="big" data-big>Slow time.</h1>
<p class="lede" data-late>Clocks and watches mended by hand, one at a time, at a bench by the window.</p>
<a class="go" href="#repairs" data-go="b" data-autoclic data-late>
<span class="go__t">Book a repair</span>
<svg class="go__arrow" viewBox="0 0 26 12" aria-hidden="true"><path d="M1 6h22M18.5 1.5 23.5 6l-5 4.5"/></svg>
</a>
</div>
<aside class="side" data-late>
<p>Wall clocks<br>Mantel clocks<br>Pocket watches</p>
<p class="side__soft">Open Tuesday to Saturday</p>
</aside>
<footer class="foot" data-late>
<span>Clockmakers</span>
<span>Since 1952</span>
</footer>
</section>
<!-- the second page: dark, its column rule on the left, where the pendulum comes to rest -->
<section class="page page--b" data-page="b" aria-label="Repairs" aria-hidden="true">
<span class="rule" aria-hidden="true"></span>
<header class="bar">
<span class="brand">Hollis</span>
<nav class="nav" aria-label="Pages">
<a href="#shop" data-go="a">Shop</a>
<a href="#repairs" aria-current="page">Repairs</a>
</nav>
</header>
<aside class="side" data-late>
<p>A repair takes as long as the clock needs.</p>
<p class="side__soft">Quotes are free</p>
</aside>
<div class="main">
<h2 class="big" data-big>Repairs</h2>
<ul class="list" aria-label="Waiting times">
<li class="row" data-late><span class="row__rule" data-rule></span><span>Wall clocks</span><span class="row__soft">3 weeks</span></li>
<li class="row" data-late><span class="row__rule" data-rule></span><span>Pocket watches</span><span class="row__soft">2 weeks</span></li>
<li class="row" data-late><span class="row__rule" data-rule></span><span>Pendulum clocks</span><span class="row__soft">4 weeks</span></li>
</ul>
<a class="go go--back" href="#shop" data-go="a" data-autoclic data-late>
<svg class="go__arrow" viewBox="0 0 26 12" aria-hidden="true"><path d="M25 6H3M7.5 1.5 2.5 6l5 4.5"/></svg>
<span class="go__t">Back to the shop</span>
</a>
</div>
<footer class="foot" data-late>
<span>Clockmakers</span>
<span>Since 1952</span>
</footer>
</section>
<!-- the pendulum: a thin rule hung above the screen -->
<span class="arm" data-arm aria-hidden="true"></span>
</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.
38 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 pendulum transition” from Animorio and fit it into my siteThe swing is a real pendulum on a sprung pivot with a little friction: θ'' = −sin θ − 6θ − c·θ', integrated in half-millisecond steps from 90 degrees, at rest. It is worked out once, resampled at 240 samples a second and rescaled so the fall lasts FALL seconds. When the rule turns back with less than nine degrees, the last stretch is a quarter of a cosine down to the upright. Then a single GSAP tween moves the time along with ease none: the stage can slow it down and the preview video sees all of it.
The new page sits on top of the old one with a clip-path polygon: the pivot and then points far away along the rays, from flat down to the lowest angle the rule has reached so far (the minimum of the samples up to that moment). So what the rule has swept stays uncovered even when it swings back. As soon as the swing has reached its furthest angle the clip-path goes and the old page is hidden.
For the first swing past the upright to uncover the whole corner on the other side, the pivot sits above the screen by distance / tan(furthest angle · 0.9): with a pendulum that calms down quickly the pivot goes up, with one that swings a lot it comes down. The rule is a div a pixel and a half wide and four screens long, with its transform-origin at the top, turned about the pivot. The pivot is worked out again every frame with the measures of the moment, so a resize halfway through the swing does not pull the rule off the edge of the slice.
Before it starts, the angle of each letter of the new title as seen from the pivot is measured and the samples are searched for the first moment the rule passes it: there, in the same timeline, the letter starts leaning by KICK degrees (skewX, with transform-origin at the bottom) with its weight at 520 on Roboto Flex's wght axis, and springs back upright and light with elastic.out.
On a phone the columns become one and the rule sits nine pixels from the edge, on the right on the first page and on the left on the second: the pendulum still sweeps the whole screen and settles on the edge. With reduced motion the two pages swap with a fade and the rule is already in place.
| Name | File | Default | What it changes |
|---|---|---|---|
FALL | script.js | 0.62 | The seconds the rule takes to fall from flat to upright; the rest of the swing follows in proportion. |
DAMPING | script.js | 1.9 | How quickly the swing dies away: 1.2 swings for long, 3 hardly swings back. |
KICK | script.js | 9 | How many degrees a letter leans when the rule sweeps past it: 0 = it stays still. |
SPEED | script.js | 1 | The speed of everything: 2 is twice as fast, 0.5 half as fast. |
To go from one page to another on a quiet site laid out in columns: a clockmaker or a watch shop, a craft workshop, an architecture or design studio, a music festival's site (the pendulum as a metronome), a portfolio with a column rule as its mark.
The same swing: the two columns become one and the rule sits close to the edge, so the pendulum falls across the whole tall screen and stops on the margin.
Nothing swings: the new page fades in over the old one, with its column rule already in place.
GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.3 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.