
Words that melt into each other
Text, Scroll, SVG
NewFree
A carved wooden cuckoo clock, drawn entirely in SVG: the hands race to the hour, the little doors spring open with a bounce, the bird bows once for every hour, the figures dance on the balcony and the pendulum speeds up; then the doors slam and the clock shakes on its nail. A click moves on to the next hour.
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>L’orologio a cucù</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="pagina">
<header class="testo">
<p class="etichetta"><span>Kuckuckhaus, clockmakers</span></p>
<h1 class="titolo">
<span class="riga"><span>Carved by hand.</span></span>
<span class="riga"><span>Opening on the hour.</span></span>
</h1>
<p class="corpo"><span>Our first clocks are still on the bench, one leaf at a time. The shop opens this winter, and the bird will let you know.</span></p>
<p class="ora" aria-live="polite"><span class="ora__dentro">It’s <span class="ora__maschera"><span class="ora__parola" data-parola>three</span></span> o’clock</span></p>
<p class="aiuto"><span>Click the clock to strike the next hour.</span></p>
</header>
<div class="palco">
<button class="orologio" type="button" data-orologio aria-label="Strike the next hour">
<svg class="orologio__svg" data-svg viewBox="-12 -40 444 872" aria-hidden="true" focusable="false">
<defs>
<linearGradient id="g-muro" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" style="stop-color: var(--legno-chiaro)" />
<stop offset="0.55" style="stop-color: var(--legno)" />
<stop offset="1" style="stop-color: var(--legno-scuro)" />
</linearGradient>
<linearGradient id="g-pilastro" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" style="stop-color: var(--legno-scuro)" />
<stop offset="0.45" style="stop-color: var(--legno-luce)" />
<stop offset="1" style="stop-color: var(--legno)" />
</linearGradient>
<radialGradient id="g-quadrante" cx="0.42" cy="0.38" r="0.7">
<stop offset="0" stop-color="#fbf4e2" />
<stop offset="0.7" stop-color="#f1e3c2" />
<stop offset="1" stop-color="#dcc597" />
</radialGradient>
<linearGradient id="g-buio" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#140c07" />
<stop offset="1" stop-color="#2c1a0f" />
</linearGradient>
<linearGradient id="g-notte" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#1d2a40" />
<stop offset="1" stop-color="#3d5068" />
</linearGradient>
<linearGradient id="g-pigna" x1="0" y1="0" x2="1" y2="0">
<stop offset="0" stop-color="#2a1b11" />
<stop offset="0.4" stop-color="#6e4c30" />
<stop offset="1" stop-color="#22150d" />
</linearGradient>
<linearGradient id="g-ottone" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#f0d58a" />
<stop offset="0.5" stop-color="#c39a45" />
<stop offset="1" stop-color="#7d5d22" />
</linearGradient>
<filter id="f-ombra" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="9" />
</filter>
<clipPath id="c-muro"><path d="M210 70 L60 196 L70 196 V560 H350 V196 L360 196 Z" /></clipPath>
<clipPath id="c-sinistra"><rect x="-40" y="-60" width="250" height="400" /></clipPath>
<clipPath id="c-destra"><rect x="210" y="-60" width="250" height="400" /></clipPath>
<!-- la pigna, disegnata dallo script: punta di sopra in (0 0) -->
<g id="pigna" data-pigna></g>
<!-- le maglie delle catene, una per catena: lo script le fa scorrere -->
<g data-maglie></g>
</defs>
<!-- tutto l'orologio, appeso al chiodo: trema quando le porte sbattono -->
<g data-tutto>
<path class="ombra" d="M210 18 L-2 214 L56 214 V600 H364 V214 L422 214 Z" transform="translate(10 16)" filter="url(#f-ombra)" />
<!-- il pendolo, dietro la cassa: gira intorno al perno -->
<g data-pendolo>
<rect x="207" y="462" width="6" height="292" rx="2" class="lb" />
<rect x="208.2" y="462" width="1.6" height="292" class="ll" opacity="0.5" />
<g data-lente></g>
</g>
<!-- le catene e le pigne -->
<g data-catene></g>
<!-- la cassa -->
<path d="M210 70 L60 196 L70 196 V560 H350 V196 L360 196 Z" fill="url(#g-muro)" />
<g clip-path="url(#c-muro)" data-venature></g>
<rect x="70" y="196" width="16" height="364" fill="url(#g-pilastro)" />
<rect x="334" y="196" width="16" height="364" fill="url(#g-pilastro)" />
<path d="M78 206 V550 M342 206 V550" class="solco" />
<rect x="64" y="410" width="292" height="10" rx="2" class="ls" />
<rect x="64" y="410" width="292" height="3" class="ll" opacity="0.6" />
<!-- la porticina dell'uccellino -->
<path d="M174 190 V146 A36 36 0 0 1 246 146 V190 Z" class="lb" />
<path d="M177 188 V146 A33 33 0 0 1 243 146 V188 Z" class="lc" />
<path d="M182 184 V146 A28 28 0 0 1 238 146 V184 Z" fill="url(#g-buio)" />
<rect x="168" y="184" width="84" height="8" rx="2" class="ls" />
<rect x="168" y="184" width="84" height="2.5" class="ll" opacity="0.7" />
<g data-porta="sinistra">
<g data-faccia="davanti">
<path d="M182 184 V146 A28 28 0 0 1 210 118 V184 Z" class="l" />
<path d="M186 180 V148 A23 23 0 0 1 206 124 V180 Z" class="ls" opacity="0.55" />
<path d="M188 178 V149 A20 20 0 0 1 204 127 V178 Z" class="lc" opacity="0.65" />
<circle cx="205" cy="156" r="2.2" fill="url(#g-ottone)" />
</g>
<g data-faccia="dietro">
<path d="M182 184 V146 A28 28 0 0 1 210 118 V184 Z" class="ls" />
<path d="M187 180 V149 A22 22 0 0 1 205 126 V180 Z" class="l" opacity="0.6" />
<path d="M186 182 V148 A23 23 0 0 1 206 124" class="solco" />
</g>
</g>
<g data-porta="destra">
<g data-faccia="davanti">
<path d="M238 184 V146 A28 28 0 0 0 210 118 V184 Z" class="l" />
<path d="M234 180 V148 A23 23 0 0 0 214 124 V180 Z" class="ls" opacity="0.55" />
<path d="M232 178 V149 A20 20 0 0 0 216 127 V178 Z" class="lc" opacity="0.65" />
<circle cx="215" cy="156" r="2.2" fill="url(#g-ottone)" />
</g>
<g data-faccia="dietro">
<path d="M238 184 V146 A28 28 0 0 0 210 118 V184 Z" class="ls" />
<path d="M233 180 V149 A22 22 0 0 0 215 126 V180 Z" class="l" opacity="0.6" />
<path d="M234 182 V148 A23 23 0 0 0 214 124" class="solco" />
</g>
</g>
<!-- l'uccellino: esce dalla porta, i piedi sul trespolo in (0 0) -->
<g transform="translate(210 186)">
<g data-uccello>
<rect x="-16" y="-1" width="40" height="5" rx="2" class="ls" />
<g data-corpo>
<path d="M-4 -12 L-6 0 M4 -12 L3 0" class="zampe" />
<g data-coda><path d="M10 -18 L44 -34 L47 -27 L42 -24 L45 -19 L14 -10 Z" class="u-scuro" /></g>
<path d="M-22 -26 C-22 -40 -2 -44 12 -34 C22 -26 18 -10 2 -9 C-12 -8 -22 -14 -22 -26 Z" class="u-corpo" />
<path d="M-21 -24 C-18 -15 -8 -11 2 -11 C-6 -16 -12 -22 -14 -30 Z" class="u-petto" />
<g data-becco-su><path d="M-31 -38 L-44 -35 L-30 -33 Z" class="u-becco" /></g>
<g data-becco-giu><path d="M-31 -33 L-41 -32 L-30 -30.5 Z" class="u-becco" /></g>
<circle cx="-22" cy="-37" r="10" class="u-corpo" />
<circle cx="-24" cy="-39" r="1.9" class="u-occhio" />
<g data-ala><path d="M-10 -30 C2 -38 20 -32 28 -22 C14 -20 0 -20 -10 -30 Z" class="u-scuro" /><path d="M-4 -29 C6 -31 14 -28 20 -24" class="u-penna" /><path d="M-2 -26 C8 -27 14 -25 18 -22" class="u-penna" /></g>
</g>
</g>
</g>
<!-- il quadrante -->
<circle cx="210" cy="300" r="104" class="lb" />
<circle cx="210" cy="300" r="101" class="ls" />
<g data-perline></g>
<circle cx="210" cy="300" r="91" class="lb" />
<circle cx="210" cy="300" r="89" fill="url(#g-quadrante)" />
<g data-tacche></g>
<g data-numeri class="numeri"></g>
<g data-ore>
<path d="M207 306 L207.5 270 C200 268 200 258 208 256 L210 247 L212 256 C220 258 220 268 212.5 270 L213 306 Z" class="lancetta" />
<circle cx="210" cy="263" r="3.2" fill="#efe1bf" />
</g>
<g data-minuti>
<path d="M208.4 308 L208.6 242 C203 240 203 233 208.6 232 L210 218 L211.4 232 C217 233 217 240 211.4 242 L211.6 308 Z" class="lancetta" />
<circle cx="210" cy="237" r="2" fill="#efe1bf" />
</g>
<circle cx="210" cy="300" r="6.5" fill="url(#g-ottone)" />
<circle cx="210" cy="300" r="2.4" fill="#3a2614" />
<!-- il balconcino coi ballerini -->
<path d="M118 526 V452 A92 36 0 0 1 302 452 V526 Z" class="lb" />
<path d="M123 526 V454 A87 32 0 0 1 297 454 V526 Z" fill="url(#g-notte)" />
<g data-sfondo></g>
<ellipse cx="210" cy="510" rx="80" ry="11" class="lb" />
<ellipse cx="210" cy="508" rx="78" ry="9" class="ls" />
<g data-ballerini></g>
<g data-ringhiera></g>
<!-- il grembiule sotto la cassa -->
<g data-grembiule></g>
<!-- il tetto -->
<g data-tetto></g>
<!-- le foglie intagliate -->
<g data-foglie></g>
</g>
</svg>
</button>
</div>
</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.
25 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 cuckoo clock” from Animorio and fit it into my siteThe page holds the skeleton of the clock (case, doors, bird, dial, balcony); everything that repeats is carved by the script with a seeded random number generator, so it comes out the same on every visit. An oak leaf is a computed path: its width follows a sine and the lobes are a second sine wave along the edge; each leaf has an offset shadow, the wood, a highlight on its upper side and veins. The shingles sit on two roof slopes: a group with a matrix that lays the x axis along the slope, rows of round shingles from the inside out, and a clipPath that cuts each slope in half, so they meet cleanly at the ridge.
WOOD is a single colour: the script derives five shades from it, mixing it towards black and towards a warm white, and writes them as CSS variables on the SVG. The wooden parts only have a class (.l, .ls, .lb, .lc, .ll) and the gradients use the variables too, with style="stop-color: var(--legno)", so changing one value changes the whole clock, shadows and highlights included.
Doors, bird, bow, beak, wings, dance, pendulum, cones and shake are numbers in one object; GSAP animates those numbers and a function on the ticker rewrites the transform attributes. So the doors fold on their hinge with scale(x 1) and, past zero, show their back; the figures go round an ellipse and are reordered front and back only when the order changes; the bird bows around its feet.
The pendulum is 29 centimetres long: its angular frequency is the square root of g over L, corrected for wide swings by dividing by 1 + θ²/16, and time comes from a phase that the ticker moves forward. During the show a multiplier on the phase rises to 1.9 and the swing grows by a quarter, then they slowly come back. The cones follow the clock: the time weight drops with the minutes, the striking weight by a notch with every bow, the free end of the chain rises by the same amount and the links, a pattern with a patternTransform, slide along with them.
Every hour is a timeline: the hands race with back.inOut (they pass the hour and come back), the doors open with back.out and a small jolt, the bird comes out, the bows are four tweens each (down with power2.in, up with back.out), the figures and the pendulum speed up; at the end the doors shut with power4.in and the shake is a series of alternating rotations that die away, around the nail. When it ends a delayedCall waits for the next hour; a click cancels it and calls the next hour at once, putting everything back in place first.
| Name | File | Default | What it changes |
|---|---|---|---|
HOUR | script.js | 3 | The hour of the first show, from 1 to 12: the hands start a little after the hour before and race to it. |
BOWS | script.js | 0 | How many times the bird bows: 0 = as many as the hour, like a real clock; any other number fixes them for every hour. |
PENDULUM | script.js | 13 | How far the pendulum swings, in degrees each way (0 = still). Wider means slightly slower, like a real pendulum. |
WOOD | script.js | '#7a4a2b' | The colour of the wood: the shadows and highlights of the carving are made from it. |
SPEED | script.js | 1 | The speed of everything, pendulum included: 2 is twice as fast, 0.5 half as fast. |
REST | script.js | 2.5 | Seconds of rest after a show before the next hour; with 0 the next hour only comes with a click. |
For a coming-soon page or the first screen of a craft workshop, a clock or wooden toy shop, a mountain bakery, a chalet hotel; for a countdown, a friendly 404 or a page that marks a time.
The same animation with the sizes adapted: the title moves to the top, centred, and the clock fills the space below; on a short screen the long text is hidden. A tap brings the next hour.
Nothing moves: pendulum and cones stay still and the hands are already on the hour; the little doors fade away and the bird appears in their place, then fades as the doors come back. The hour line changes with a fade.
GSAP 3.15.0, Fraunces (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 13 KB; the libraries: GSAP 28 KB.
Tested on 10 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.