
The menu under the page
Menus, 3D, Physics, Transitions
NewFree
The menu of a tea house as a Japanese folding fan of paper and bamboo, in 3D: closed it is the black lacquer guard with Menu in gold and a silk tassel hanging from the rivet. Pressed, the sticks spread round the rivet one after another, each on its own spring, the pleated paper pulls taut between them and stops them, and the fan rocks for a moment as if just flicked open. Every pair of pleats is a section, printed on the painted paper (a plum branch, a gold leaf moon, waves at the foot). Hovered, the section’s pleats rise and its name lights up; chosen, they dip and the sticks fold back.
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 fan menu</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/zen-old-mincho@5.3.0/500.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/zen-old-mincho@5.3.0/700.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the paper fan menu, for a tea house: the closed fan, its lacquered guard and silk tassel, is the Menu button.
Pressed, the sticks spread round the rivet one after another, the pleated paper pulls taut between them and
every pair of pleats carries a section, printed on the painted leaf. The fan is drawn in 3D on a canvas: the
sticks, the pleats folded back and forth, the painting mapped onto every facet, the light on each fold -->
<div class="fan" data-fan>
<canvas class="fan__canvas" aria-hidden="true" data-canvas></canvas>
<button class="fan__btn" type="button" aria-expanded="false" aria-controls="fan-menu" data-btn data-autoclic>
<span class="sr" data-name>Open the menu</span>
</button>
<!-- the sections: real links, one for each pair of pleats (the canvas prints them on the paper) -->
<nav class="fan__nav" id="fan-menu" aria-label="Main" data-nav inert>
<ul>
<li><a href="#teas" data-item>Teas</a></li>
<li><a href="#sweets" data-item>Sweets</a></li>
<li><a href="#ceremony" data-item>Ceremony</a></li>
<li><a href="#classes" data-item>Classes</a></li>
<li><a href="#shop" data-item>Shop</a></li>
<li><a href="#visit" data-item>Visit</a></li>
</ul>
</nav>
<p class="sr" aria-live="polite" data-live></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.
29 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 fan menu” from Animorio and fit it into my siteThe fan is a real model: thirteen sticks turning round the rivet, the two lacquer guards outside and the eleven bamboo ones inside, and the paper split into twenty four facets by creases that all start at the rivet. Every frame the script works out the points in three dimensions, rocks them, leans them back (TILT) and turns them, and projects them in perspective; the facets are sorted by depth and painted from the back forwards, between the sticks behind and the front guard.
Every facet, flat, always has the same angle b at the rivet. Two neighbouring sticks are g apart: the fold between them sits where the two facets keep their width, so it goes back by an angle e with cos e = cos b / cos(g / 2). So the pleats deepen as the fan closes and go flat when the paper is taut; TAUT says how pleated they stay with the fan open.
Each stick has its own spring (SPRING) towards its place, which it gets a moment after the one before (STAGGER). After each step a constraint, as in position based physics, stops two sticks parting further than the paper is wide, and passing through each other: the front guard, the first to set off, pulls the others behind it on the taut paper and the bounce dies on the paper. As soon as the fan is open, a lightly damped spring on the whole turn makes it rock (ROCK).
The paper is painted only once, laid flat, on a canvas of its own: the paper with its fibres, the seigaiha waves, the gold leaf moon, the plum branch in brush strokes, the blossoms, the flakes, the seal and the sections, letter by letter along the arc. Every facet is drawn as six triangles: for each the script works out the affine transform that takes the triangle of the flat painting onto the triangle on screen, clips a hair larger (no seams) and pastes the painting in. Then a light or dark veil, from the facet’s normal, gives the pleats their light.
Hovered, the section’s pleats slide out along their creases and towards the viewer (LIFT), with a soft shadow under them, and over their facets a second painting with the names in vermilion and a gold glow fades in. The tassel is a verlet chain hung from the rivet, stepped in even 1/240 s steps so it gains no energy from uneven frames; opening and closing give it a knock. When nothing moves the canvas is not redrawn.
The fan is a button with aria-expanded and aria-controls, laid along the closed fan (turned with it) and, open, over the rivet. The sections are real links in a nav, inert while it is closed, that the canvas prints on the paper: the arrows, Home and End go from one to the next with an outline on the pleats, Enter chooses, Escape closes and the focus goes back to the fan; an aria-live area reads out the section chosen. A tap on a section lifts it and, let go there, chooses it.
| Name | File | Default | What it changes |
|---|---|---|---|
OPEN_ANGLE | script.js | 156 | How wide the open fan spreads, in degrees. |
TAUT | script.js | 0.93 | How taut the paper is once open: 1 is flat, less leaves deeper pleats. |
SPRING | script.js | [95, 0.55] | The spring of every stick: stiffness, and damping (1 = no bounce). |
STAGGER | script.js | 0.055 | The seconds between one stick setting off and the next. |
ROCK | script.js | 4 | How far the fan rocks once it is open, in degrees. |
TILT | script.js | 12 | How far the open fan leans back, in degrees. |
LIFT | script.js | 16 | How far a section rises out of the fan under the pointer, in units of the drawing. |
PEEK | script.js | 9 | How far the front guard swings out under the pointer while the fan is closed, in degrees. |
For the menu of a site with a crafted, Japanese character: a tea house, a Japanese restaurant, a wagashi confectioner, a ryokan, a paper shop, a spring festival. Six short sections, one per pair of pleats; long words get narrowed.
The whole drawing scales to the width of the screen (at 390 pixels the box is 358) and the open fan fits without spilling over; the painting is painted again at the new size. A tap on a section lifts it like the mouse over it, and letting go there chooses it; the rivet and a tap outside close it.
No running sticks, turns or rocking: the fan fades out and back in already open, or already closed, the tassel hangs still and the section under the pointer lights up without rising.
GSAP 3.15.0, Zen Old Mincho 5.3.0.
Compressed with gzip, the three demo files weigh 18 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.