
The cube stories
Stories, 3D, Transitions
NewFree
An osteria's menu as a little book: the page is turned by taking its edge, which follows the finger round the spine in 3D; it darkens as it rises and throws its shadow on the page below, and let go past the middle it turns over by itself, otherwise it falls back. On a computer it lies open on two pages, on a phone it turns one page at a time.
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 menu to leaf through</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/eb-garamond@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the menu to leaf through: a page turned by its edge follows the finger round the spine, darkens as it rises
and throws its shadow on the page below; let go past the middle it turns over, otherwise it falls back -->
<section class="menu" aria-label="The osteria's menu" data-menu data-autoclic>
<div class="book" tabindex="0" aria-roledescription="book" data-book>
<div class="book__shade book__shade--left" aria-hidden="true" data-shade-left></div>
<div class="book__shade book__shade--right" aria-hidden="true" data-shade-right></div>
</div>
<nav class="leaf" aria-label="Pages">
<button class="leaf__btn" type="button" aria-label="Previous page" data-prev><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M14.5 6l-6 6 6 6"/></svg></button>
<p class="leaf__where"><span class="roll" data-where></span></p>
<button class="leaf__btn" type="button" aria-label="Next page" data-next><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M9.5 6l6 6-6 6"/></svg></button>
</nav>
<p class="sr" aria-live="polite" data-live></p>
</section>
</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.
83 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 menu to leaf through” from Animorio and fit it into my siteEach sheet hangs from the spine (transform-origin on its left edge) and has two faces: front and back, turned 180 degrees, both with backface-visibility hidden; the sheet has transform-style preserve-3d and the perspective is on the book. Open on two pages a sheet carries the right page on its front and the left one on its back; one page at a time, it carries a single page and a blank back.
The sheet's angle is the one whose projection on the table reaches the pointer: −acos(distance from the spine / page width). So the edge stays under the finger; a 0.18-second tween takes it there, so that a sheet taken from the spine opens without jumps.
On each face there is a dark veil whose opacity is the sine of the angle: nothing with the page lying flat, full when edge-on. On the page below a shadow falls from the spine, on the right while the sheet rises and on the left when it comes down on the other side.
Let go past the middle, or with a flick faster than FLICK pixels a second, the sheet goes to −180 or to 0; otherwise it comes back with back.out. A tap on the right turns forwards, on the left backwards. On a phone the finger cannot go past the spine, so two thirds of the way is enough, and past the spine the sheet fades. Turned pages lie on the left with a growing z-index, pages to turn on the right with a falling one, and the moving sheet above all.
Closed, the book moves by half a page so the cover sits in the middle, and opening it comes back with the spine in the middle. The arrows under the book and those of the keyboard turn the pages, Home and End go to the start and the end; with the mouse near the edge the corner lifts by LIFT degrees. A click from a script (the library's preview) turns the next page and, at the end, closes the book page after page.
| Name | File | Default | What it changes |
|---|---|---|---|
PLACE | script.js | ['Osteria', 'La Lanterna'] | The name on the cover, in two lines. |
PAGES | script.js | [['cover'], ['Starters', 'Antipasti', [['Bruschetta', 'Tomatoes, basil, new oil', 7], …]], …, ['thanks']] | The pages: the name under the book, the title on the page and the dishes (name, what is in it, price); cover and thanks are the cover and the last page. |
TURN | script.js | 0.75 | The seconds a page takes to turn by itself. |
LIFT | script.js | 8 | The degrees the corner lifts under the mouse. |
FLICK | script.js | 700 | The speed, in pixels a second, that turns a page even before the middle. |
For the menu of a restaurant or a farm stay, a wine list, a catalogue, a brochure, a wedding booklet, a magazine: anything that reads better leafed through.
Under 640 pixels the book shows one page at a time, up to 360 pixels wide: the finger turns it towards the spine, from right to left, and brings it back starting from its left third; the page does not scroll the screen (touch-action none on the book).
Pages turn at once, with the buttons, the keys and letting go of the finger (which still moves the page while dragging); the corner does not lift with the mouse and no entrance.
GSAP 3.15.0, EB Garamond (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.7 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.