
The mechanical key button
Buttons, 3D, Physics, SVG
NewFree
A wall calendar on a black background, a cream sheet for each month hanging from a wire binding: turning the page the sheet lifts up over the binding in 3D, darkening and showing its back, and the chosen day is circled by hand with a red marker.
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 paper calendar</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/opsz.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/opsz-italic.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<div class="calendar" data-calendar>
<!-- the arrows (below the pad on screen, first for the Tab key) -->
<div class="calendar__nav">
<button class="calendar__arrow" type="button" aria-label="Previous month" data-prev><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 15l6-6 6 6"/></svg></button>
<button class="calendar__arrow" type="button" aria-label="Next month" data-next data-autoclic><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M6 9l6 6 6-6"/></svg></button>
</div>
<!-- the pad: a wire binding, the sheet of the month, and the edges of the sheets below.
Turning a page, a copy of the sheet swings up over the binding in 3D while the new month waits underneath -->
<div class="pad" data-pad>
<div class="pad__sheets" data-sheets></div>
<svg class="pad__wire" data-wire aria-hidden="true"></svg>
</div>
<p class="sr" role="status" aria-live="polite" data-said></p>
</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.
13 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 paper calendar” from Animorio and fit it into my siteEach month is a section drawn by the script: the year, the month, the initials of the days from WEEK_START on and six weeks of buttons. Over the days sit an empty SVG for the ink and a dark veil for the shadow. The binding is an SVG drawn again for the width of the calendar: a loop about every 24 pixels, each with its hole in the paper and two wires.
The moving sheet goes into a box with transform-style: preserve-3d and its pivot on the top edge, together with a back face turned by 180 degrees; both have backface-visibility: hidden. A number goes from 0 to 180 degrees in FLIP seconds with power2.inOut, and on every frame it becomes the box’s rotationX. The container has the perspective (DEPTH pixels) seen from the top edge, so the sheet lifts towards you.
The same number darkens the turning sheet, with a veil that reaches LIGHT at 90 degrees, and the sheet below, with LIGHT times 0.8 times the sine of the angle: the shadow is there while the sheet is lifted. Past 120 degrees the two faces fade, each on its own.
The ring is an ellipse of 72 points, slightly tilted, with a shake made of a sine and a little chance (WOBBLE), that goes round 1.14 times and widens a little as it goes. The chance comes from a generator seeded with the date, so the same day always gets the same ring. It is drawn by taking the stroke-dashoffset from the length of the stroke to zero in INK seconds, and rubbed out the other way.
The arrows come before the calendar in the code (and below it on screen, with order), so the Tab key finds them first; then a single day takes the Tab key: the arrow keys move between the days, Page Up and Page Down turn the pages, Enter circles. With a finger a swipe of at least 40 pixels turns the page, and the tap it ends with chooses no day.
| Name | File | Default | What it changes |
|---|---|---|---|
WEEK_START | script.js | 1 | The first day of the week: 1 Monday, 0 Sunday. |
FLIP | script.js | 1 | The seconds of a page turning. |
LIGHT | script.js | 0.35 | How dark a sheet gets as it turns away from the light, and the shadow it throws on the one below. |
INK | script.js | 0.6 | The seconds the marker takes to draw a ring. |
WOBBLE | script.js | 0.07 | How shaky the hand is: 0 draws a perfect ellipse. |
DEPTH | script.js | 1600 | The perspective, in pixels: the smaller it is, the more the sheet comes towards you. |
For the events page of a venue, a theatre or a festival, for an advent calendar or a countdown: wherever one month at a time is shown and the calendar can also be an object.
The calendar narrows to the width of the screen and taps choose the days like clicks. On top of that, a swipe upwards turns the page and a swipe downwards goes back.
The page doesn’t turn: the new month fades in over the old one in a quarter of a second. The marker doesn’t draw, the ring appears already made, and when the page opens the calendar is already in place.
GSAP 3.15.0, Fraunces (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.5 KB; the libraries: GSAP 28 KB.
Tested on 3 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.