Skip to content
animorio
IT
All components

The Advent calendar

Calendars, 3D, Physics, SVGGSAP, CanvasAdvancedCompressed weight: Demo 24 KBGSAP 28 KBFreeDownload the zip

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.

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

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.

35 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 Advent calendar” from Animorio and fit it into my site

What it does

On a white background there is a cream card calendar with a winter street drawn on it: a blue sky warming towards the horizon, the moon, snowy hills, a fir tree with a gold garland, the Thimble & Pine shop in red brick with its roof under the snow, the sign, the striped awning and two lanterns, the bakery next door and parcels in the snow. The 24 windows are part of the drawing: arched windows with red curtains, the round gable window, the chimney, the shop windows, the moon, the bauble on top of the tree, the parcels and the double front door for the 24th, with the dates in gold foil and a perforated edge. When the page opens the calendar rises and the windows of the days gone open one after the other. Pressing a closed window of a day gone, or today’s, the free edge lifts and the card bends while the perforation holds, then it tears: the leaf swings on its hinge, goes a little past, comes back and stays slightly curled. Inside is a warm little room with a shelf and the day’s present (a discount, a biscuit, a candle, a mug of cocoa…), which jumps out spinning among little stars, drops back and squashes onto the shelf. Below, the date and the line with the present change. Pressing again shuts the window, which bangs against its frame. The windows of the days to come are sealed: they lift a hair, bang and rattle, and the line says in how many days they open. Today’s has a gold frame and a warm glow: snow falls on it and banks up on the sill, and a gleam runs across its number. With a mouse over it, a window lifts its corner.

How it works

The street and the windows

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

A leaf made of strips

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.

Two springs: the hinge and the paper

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.

The light on the curve

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.

The present and the snow

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.

Keyboard, mouse and finger

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.

Values to change

NameFileDefaultWhat it changes
DEMO_DAYscript.js11The day of December that counts as today outside December (in December the calendar follows the real date; 25 opens them all).
OPEN_ANGLEscript.js108How far an open window swings on its hinge, in degrees.
SWINGscript.js[70, 10]The hinge spring: stiffness and damping.
FLEXscript.js[240, 15]The card’s spring: stiffness and damping (softer, the more it wobbles).
LAGscript.js1How much the card lags behind the hinge and bends.
CURLscript.js14How curled an open window stays, in degrees.
STRIPSscript.js6The strips every leaf is cut into to bend: more strips, a smoother curve.
SNOWscript.js[3.6, 70]The snow on today’s window: the seconds of a snowfall, and the flakes a second.
POPscript.js1.6How big the present gets when it jumps out.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • A leaf opening towards the viewer is enlarged by the perspective almost as much as it is foreshortened: at small angles it looked still. What made it show is the light per strip (one side brightens, the other darkens) and the dark of the little room, which stays while the leaf is barely lifted.
  • The card must not pass into the street: when the backward curve goes past the hinge’s angle it is stopped there, or the tip of the leaf ended up behind the drawing and the browser cut it off.
  • The strips’ shading changed inside an SVG on every frame forced the browser to draw them all again: a brightness filter on the strip, which already has its own layer, is applied without drawing again.
  • Shut and still windows go back to a flat drawing (no rotateY, back hidden): with 24 leaves of strips always in 3D the layers became hundreds.
  • Tilting the whole calendar towards the pointer made it blurry, because the browser drew it again at low resolution inside the perspective: the tilt was dropped.
  • The gleam on today’s numbers is one SVG gradient shared by all the copies of the leaf: it moves by shifting its x1 and x2, once, without touching the twenty copies of the drawing.

Libraries

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.

Testing

Tested on 17 October 2026

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

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 components