
The variable weight menu
Menus, Text, Hover, Physics
NewFree
The near-black footer of a small watchmaker, with a wall of little three-handed clocks along the bottom: together, the hands write the atelier's name. The clocks near the pointer turn their hands to look at it and glow red, a link pointed at sends a wave across the wall until it spells that link's word, a tap sends out a ring of full turns, and signing up to the letter winds every clock before the wall says thank you.
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 clock-wall footer</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the footer of a small watchmaker: along the bottom a wall of little clocks, each with three hands, and the
hands together write the atelier's name. Every clock looks at the pointer as it passes, a link pointed at
makes the whole wall turn its hands and spell that link's word, a tap sends a ring of spinning hands out
from the finger, and signing up to the letter winds every clock before the wall says thank you -->
<footer class="cw" data-footer data-autoclic>
<div class="cw__top">
<form class="cw__form" action="#" novalidate aria-labelledby="cw-news" data-form>
<h2 class="cw__title" id="cw-news">Notes from the bench</h2>
<p class="cw__lede">New pieces and repair stories, once a month.</p>
<label class="sr" for="cw-email">Email address</label>
<div class="cw__field" data-field>
<input class="cw__input" id="cw-email" name="email" type="email" inputmode="email" autocomplete="email" autocapitalize="off" spellcheck="false" enterkeyhint="send" placeholder="you@example.com" aria-describedby="cw-note" aria-invalid="false" data-input>
<button class="cw__send" type="submit" data-send>
<span class="cw__send-bg"></span>
<span class="cw__send-label" data-send-label>Subscribe</span>
<svg class="cw__spin" viewBox="0 0 24 24" aria-hidden="true" data-spin><circle cx="12" cy="12" r="8.2"/><path class="cw__spin-hand" d="M12 12V7" data-spin-hand/><path d="M12 12l2.6 1.6"/></svg>
<svg class="cw__done" viewBox="0 0 24 24" aria-hidden="true" data-done><path d="M6.4 12.6l3.7 3.7 7.6-8.6"/></svg>
</button>
</div>
<p class="cw__note" id="cw-note" aria-live="polite" data-note><span class="cw__line">No spam, ever. Leave with one click.</span></p>
</form>
<nav class="cw__cols" aria-label="Footer">
<div class="cw__col">
<h3 class="cw__head">Shop</h3>
<ul class="cw__list">
<li><a class="cw__link" href="#" data-link data-word="WATCH">Watches</a></li>
<li><a class="cw__link" href="#" data-link data-word="STRAP">Straps</a></li>
<li><a class="cw__link" href="#" data-link data-word="GIFTS">Gifts</a></li>
</ul>
</div>
<div class="cw__col">
<h3 class="cw__head">Atelier</h3>
<ul class="cw__list">
<li><a class="cw__link" href="#" data-link data-word="STORY">Our story</a></li>
<li><a class="cw__link" href="#" data-link data-word="NOTES">Bench notes</a></li>
<li><a class="cw__link" href="#" data-link data-word="VISIT">Visit us</a></li>
</ul>
</div>
<div class="cw__col">
<h3 class="cw__head">Help</h3>
<ul class="cw__list">
<li><a class="cw__link" href="#" data-link data-word="CARE">Care guide</a></li>
<li><a class="cw__link" href="#" data-link data-word="SHIP">Shipping</a></li>
<li><a class="cw__link" href="#" data-link data-word="HELLO">Contact</a></li>
</ul>
</div>
</nav>
</div>
<!-- the wall: one canvas, a few dozen clocks a row; the hands write the name, and the word of the link pointed at -->
<div class="cw__wall" data-wall>
<canvas class="cw__clocks" aria-hidden="true" data-clocks></canvas>
</div>
<div class="cw__base">
<p class="cw__brand">
<svg class="cw__mark" viewBox="0 0 28 28" aria-hidden="true"><circle class="m-case" cx="14" cy="14" r="12.2"/><path class="m-moon" d="M17.6 7.4a7 7 0 1 0 0 13.2 6 6 0 0 1 0-13.2z"/><path class="m-hand" d="M14 14l4.6-3.4"/></svg>
<span class="cw__name">Lune Watchmakers</span>
<span class="cw__copy"><svg viewBox="0 0 12 12" aria-hidden="true"><circle cx="6" cy="6" r="5.1"/><path d="M7.9 4.5a2.3 2.3 0 1 0 0 3"/></svg><span class="sr">Copyright</span> 2026 Lune Atelier</span>
</p>
<nav class="cw__legal" aria-label="Legal">
<a class="cw__link cw__link--small" href="#" data-link>Terms</a>
<a class="cw__link cw__link--small" href="#" data-link>Privacy</a>
</nav>
</div>
</footer>
</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.
47 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 clock-wall footer” from Animorio and fit it into my siteEach letter is a grid of three clocks by five, and for each clock it says where its hands point, one digit a hand read like the number pad (8 north, 6 east, 3 south-east, 1 south-west...); a dot is a clock at rest. A hand pointing at a clock that points back draws a whole stroke between the two centres; a three-way joint uses the third hand, and the hands that are not needed park on top of the others. A writing hand is as long as the way to the edge of its clock's square: half a clock straight across, more on a diagonal, so the slanted strokes meet too.
The wall lays out as many clocks as fit at CELL pixels, but never fewer than the longest word needs (four columns a letter, less the last gap), and always an odd number, like the words: so every word sits exactly in the middle. On a phone the clocks get smaller until the longest word fits. The canvas is drawn at the screen's density, the raised face once on a canvas of its own, then copied.
Every hand is a damped spring chasing its angle, in steps of 1/120 of a second, and when everything is still the loop goes to sleep. Its angle is a sum: the word (which GSAP moves with a function stagger, a wave from left to right and a little later lower down), the rings of full turns, the winding and the shaking head. GSAP only moves the goals: the hands get there by themselves and, with BOUNCE, swing past and come back like real ones.
For each clock the distance from the pointer gives a weight, from 1 under the pointer to 0 at REACH clocks, along a soft curve. The goal of each hand moves towards the pointer's direction by that weight, always the short way round; the same weight lengthens the hands and mixes their colour towards red. The weight rises quickly and falls slowly, so the clocks turn at once and go back to the word calmly.
The rings and the winding do not touch the word's angle: they have their own terms. A ring adds a whole turn, one way or the other, with a delay that grows with the distance from the click. The winding turns at three whole speeds (once, twice and three times); on a sign-up it slows down to an exact number of turns and is then moved into the hand, so nothing jumps. Each new word is worked out from where every hand is going, not from where it is, so it always lands right.
| Name | File | Default | What it changes |
|---|---|---|---|
NAME | script.js | 'LUNE' | The word the wall writes at rest: up to five letters, A to Z. |
THANKS | script.js | 'MERCI' | The word the wall writes when someone signs up. |
CELL | script.js | 28 | How big each little clock is on a computer, in pixels (smaller on a phone, so the longest word fits). |
REACH | script.js | 4 | How many clocks away the hands still turn to look at the pointer. |
BOUNCE | script.js | 0.45 | How far the hands swing past where they stop and back: at 0 they stop dead. |
SWEEP | script.js | 1.1 | How long the hands take to turn to a new word, in seconds. |
WAVE | script.js | 0.02 | The delay from one column of clocks to the next, in seconds: the wave that runs across the wall. |
DIM | script.js | 0.22 | How bright the hands of the clocks outside the word are, from 0 to 1. |
WAIT | script.js | 1.4 | How long the sign-up takes in the demo, in seconds, while every clock winds. |
For the footer of a watchmaker, a jeweller, a design shop or a brand of precision objects, but also a studio, a festival or an app that wants a name that moves: anywhere the bottom of the page can be a small kinetic show, with short words for the links.
The footer takes the width of the screen: the letter goes on top and the three columns of links stay side by side, with 44-pixel rows to tap. The wall has nineteen clocks a row, smaller, so the longest word fits whole. A tap on a link lights the word and the wall writes it for a couple of seconds; a finger dragged sideways on the wall is watched by the clocks (up and down scrolls the page), and a tap sends the ring of turns.
No hand turns: the wall fades in with the name already written, and when the word changes it dims for a moment and comes back with the new word already in place. The clocks do not watch the pointer, a tap sends no ring, a wrong field does not shake and the hands do not shake their heads, a sign-up does not wind the wall and MERCI fades in. The links light up without ticking forward, the button does not narrow and its hand keeps still.
GSAP 3.15.0, Instrument Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 14 KB; the libraries: GSAP 28 KB.
Tested on 13 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.