
The mechanical key button
Buttons, 3D, Physics, SVG
NewFree
A shop’s Advent calendar, printed as a winter street at dusk with 24 windows cut into the card: the windows of the days gone open on their hinges, bending the paper, and inside, in a little lit room, a drawn present jumps out and lands back on its shelf; the days to come are sealed and rattle; snow falls on today’s 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 Advent calendar</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/fraunces@5.3.0/full-italic.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the Advent calendar of a little shop: 24 windows cut into a printed winter street. The days gone open on their
hinges, bending the cardboard, and a present jumps out; the days to come are sealed and rattle; today's window
has its own snow. The street, the windows and the presents are drawn by the script -->
<div class="advent" data-advent data-autoclic>
<div class="advent__card">
<div class="advent__scene" data-scene>
<svg class="advent__art" viewBox="0 0 520 600" preserveAspectRatio="none" aria-hidden="true" data-art></svg>
<div class="advent__doors" role="group" aria-label="December, 24 windows" data-doors></div>
<canvas class="advent__snow" aria-hidden="true" data-snow></canvas>
<span class="advent__grain" aria-hidden="true" data-grain></span>
</div>
<div class="advent__pop" aria-hidden="true" data-pop></div>
<div class="advent__foot">
<p class="advent__date" data-date></p>
<p class="advent__line" data-line></p>
</div>
</div>
<p class="sr" role="status" aria-live="polite" data-said></p>
</div>
</main>
<!-- the gold foil of the numbers and the light inside the windows, shared by every drawing -->
<svg class="defs" width="0" height="0" aria-hidden="true" focusable="false">
<defs>
<linearGradient id="av-gold" x1="0" y1="0" x2="0.35" y2="1">
<stop offset="0" stop-color="#fff3c4"/>
<stop offset="0.38" stop-color="#f1c45a"/>
<stop offset="0.62" stop-color="#c98d22"/>
<stop offset="1" stop-color="#f6d47c"/>
</linearGradient>
<linearGradient id="av-sheen" x1="-1" y1="0" x2="0" y2="0.4" data-sheen>
<stop offset="0" stop-color="#f1c45a"/>
<stop offset="0.42" stop-color="#e2a83a"/>
<stop offset="0.5" stop-color="#fffbe8"/>
<stop offset="0.58" stop-color="#e2a83a"/>
<stop offset="1" stop-color="#f6d47c"/>
</linearGradient>
<linearGradient id="av-room" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#b9532a"/>
<stop offset="0.45" stop-color="#f09a45"/>
<stop offset="1" stop-color="#ffd98a"/>
</linearGradient>
<linearGradient id="av-glass" x1="0" y1="0" x2="0" y2="1">
<stop offset="0" stop-color="#2b3a6e"/>
<stop offset="0.55" stop-color="#6b4d6c"/>
<stop offset="1" stop-color="#f3a957"/>
</linearGradient>
<linearGradient id="av-kraft" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#f6e9cd"/>
<stop offset="1" stop-color="#e0cba3"/>
</linearGradient>
</defs>
</svg>
<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.
35 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 Advent calendar” from Animorio and fit it into my siteThe street is a single SVG of 520 by 600 units, drawn by the script: the sky, four-pointed stars, the hills, the shop with bricks made from an SVG pattern, the roof, the tiered fir, the snow and the window frames. The 24 windows are buttons placed over it in percentages, with their shape, drawing and hinge side written in SLOTS; the numbers are dates, shuffled as in real calendars.
Every leaf is cut into STRIPS strips, one inside the other: each strip turns with rotateY on the edge of the one before it, inside one perspective shared by all the windows. The first strip is the crease of the hinge, the others share the curve of the card. Each strip shows its own piece of the drawing (a copy of the SVG moved to the left) and, on its back, plain card; leaves hinged on the right are the same ones, mirrored.
The hinge’s angle goes to OPEN_ANGLE on a spring (SWING); the curve of the paper is a second spring (FLEX) pushed back by the hinge’s acceleration (LAG), so the free edge lags behind when the leaf sets off, overtakes it when it stops and settles. Four small steps per frame, with the step capped at 1/30 of a second; once open, the leaf stays curled by CURL degrees. On a real opening the edge lifts for a moment with the paper bent and the hinge still, then the perforation gives.
Each strip is lit by its own angle, with the light coming from the front and a little from the right: a brightness filter on the strip, which the browser applies without drawing it again. That way the curve of the card shows as a gradient. In the little room the dark stays while the leaf is barely lifted, and the open leaf throws its shadow on the wall by the hinge.
When the leaf passes 50 degrees a copy of the present leaves the little room in a layer above the calendar: GSAP lifts it, enlarges it (POP) and spins it among seven little stars, then drops it back and squashes it with an elastic ease. Today’s snow is a canvas: the flakes fall in a column above the window, fading at the sides, and those touching the sill raise the drift where they land; the snowfall lasts SNOW seconds, then the loop stops.
A single day takes the Tab key (today’s at first): the arrows go to the day before and the day after, Home and End to the first and the 24th, Enter opens or shuts. With a mouse, or the keyboard’s focus, the window lifts its corner; with a finger it lifts while you press. The leaves, the springs and the snow all go through one requestAnimationFrame, which stops when nothing moves.
| Name | File | Default | What it changes |
|---|---|---|---|
DEMO_DAY | script.js | 11 | The day of December that counts as today outside December (in December the calendar follows the real date; 25 opens them all). |
OPEN_ANGLE | script.js | 108 | How far an open window swings on its hinge, in degrees. |
SWING | script.js | [70, 10] | The hinge spring: stiffness and damping. |
FLEX | script.js | [240, 15] | The card’s spring: stiffness and damping (softer, the more it wobbles). |
LAG | script.js | 1 | How much the card lags behind the hinge and bends. |
CURL | script.js | 14 | How curled an open window stays, in degrees. |
STRIPS | script.js | 6 | The strips every leaf is cut into to bend: more strips, a smoother curve. |
SNOW | script.js | [3.6, 70] | The snow on today’s window: the seconds of a snowfall, and the flakes a second. |
POP | script.js | 1.6 | How big the present gets when it jumps out. |
For the Christmas page of a shop, a pastry shop, a brand or an app: a present or a discount a day from 1 to 24 December, a newsletter campaign, the Advent calendar of a blog or an event. The presents, the discounts and the codes should come from your own system instead of the made-up ones, and the drawing of the street is changed in the SVG.
The calendar narrows to the width of the screen and the whole drawing, the windows and the perspective are measured on it, so they stay in proportion; every window has a few extra pixels around it for the finger. With a finger the window lifts its corner while you press, and the date goes above the line with the present. Same leaves, same springs and same snow as on a computer.
No springs, no jumps and no falling snow: the windows of the days gone are already open, a window opens or shuts at once and the present fades in; the ones to come don’t rattle and the line below says so; on today’s window the snow stands still in the air and the drift is already on the sill.
GSAP 3.15.0, Fraunces (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 24 KB; the libraries: GSAP 28 KB.
Tested on 17 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.