Skip to content
animorio
IT
All components

The paper fan menu

Menus, 3D, Physics, TransitionsCanvas, GSAPAdvancedCompressed weight: Demo 18 KBGSAP 28 KBFreeDownload the zip

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.

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

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.

29 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 paper fan menu” from Animorio and fit it into my site

What it does

On a white background a closed fan, leaning a little to the right: in front the black lacquer guard with two plum blossoms and the word Menu in gold, behind it the edge of the folded paper, at the bottom the brass rivet with a vermilion silk tassel swinging from it. With the mouse over it, the front guard swings out a few degrees and uncovers the first painted pleats. Pressed, the sticks spread round the rivet one after another, from the front guard to the back one; the paper between them pulls taut until it lies flat and stops them, then relaxes into its pleats, while the fan turns towards you; open, it rocks for a moment on its rivet and the tassel swings. The paper is painted: at the top a plum branch in ink with white and pink blossoms and a gold leaf moon, at the foot seigaiha waves in indigo under a gold edge, here and there gold flakes and the red seal of the house. The pleats facing up catch the light from the top left, the folds in between lie in shade, and the painting bends with the paper. Every pair of pleats carries a section, written along the arc: Teas, Sweets, Ceremony, Classes, Shop, Visit. Hovered, the section’s pleats rise out of the fan with their shadow and its name turns vermilion with a gold glow; pressed, the section dips, the sticks fold back from the last to the first and the front guard comes over them last; the chosen section stays in bold. The rivet of the open fan closes it, as do Escape and a click outside. From the keyboard the arrows go from section to section, with an outline round its pleats, Enter chooses.

How it works

A 3D fan on a canvas

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

The paper is rigid between its creases

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.

Sticks on springs, stopped by the paper

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 painting laid on the facets

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.

The section lighting up, and the tassel

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.

Keys and accessibility

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.

Values to change

NameFileDefaultWhat it changes
OPEN_ANGLEscript.js156How wide the open fan spreads, in degrees.
TAUTscript.js0.93How taut the paper is once open: 1 is flat, less leaves deeper pleats.
SPRINGscript.js[95, 0.55]The spring of every stick: stiffness, and damping (1 = no bounce).
STAGGERscript.js0.055The seconds between one stick setting off and the next.
ROCKscript.js4How far the fan rocks once it is open, in degrees.
TILTscript.js12How far the open fan leans back, in degrees.
LIFTscript.js16How far a section rises out of the fan under the pointer, in units of the drawing.
PEEKscript.js9How far the front guard swings out under the pointer while the fan is closed, in degrees.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • With the pleats folded forwards, towards the viewer, the closed fan had its paper in front of the lacquer guard: the pleats fold backwards and the front guard covers the whole stack.
  • A painting pasted triangle by triangle left thin seams along the diagonals: every triangle is clipped three quarters of a pixel wider than itself, and copies only the rectangle of the painting it needs.
  • The tassel, a verlet chain, never came to rest: steps as long as the frame, each different from the last, gave it energy every frame and the canvas redrew forever. Now it takes even 1/240 s steps, its damping depends on time and not on the number of steps, and it counts how far it moved since the frame before.
  • At first everything opened in a third of a second and the sticks setting off one after another could not be seen: the spring is softer and the starts further apart, so the front guard pulls the taut paper behind it and the others arrive after.
  • The canvas uses the typeface without any element asking for it, and the seal an ideogram that lives in another piece of the font: they are loaded by hand with document.fonts.load (with the ideogram as its text too) and then the paper is painted again.
  • Making the chosen section bold at once, with the fan still open, made the word jump: the paper is painted again once the fan is closed.

Libraries

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.

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