
The vase in the sun
Cards, 3D, Physics, Hover, Transitions
NewFree
The menu of a festival in the woods as a post with painted wooden arrows: closed, it is the oak board at the top of the post, with Menu burnt into the wood. Pressed, the board spins on the post and its back reads Close, the post slides down, bounces and sets the sign swaying, and each arrow, as the post reaches it, is flung out to the left or the right and wobbles on its spring, passing the wobble to the others. The pointer brushing an arrow pushes it back and sets it swinging, with its letters bouncing; the chosen one flips over on its long side.
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 signpost menu</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/shantell-sans@5.3.0/full.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the menu of a summer festival in the woods as a wooden signpost. Closed, the button is the oak board nailed to
the top of the post. Pressed, the board spins round on the post and reads Close, the post slides down out of
it, and as its end goes past each arrow the arrow is flung out round the post, left and right in turn, and
wobbles on its spring; the wobble runs up and down the post into the other arrows. The pointer brushing an
arrow pushes it back and lets it swing; a chosen arrow flips over on its long side. The boards are flat
elements turned in 3D by the script, with their thickness made of thin slices -->
<nav class="sign" aria-label="Festival" data-sign>
<div class="sign__frame" data-frame>
<div class="sign__scene" data-scene>
<span class="pole" aria-hidden="true" data-pole><span class="pole__wood"></span></span>
<svg class="cap" viewBox="0 0 34 14" aria-hidden="true"><path d="M3 13 L17 1 L31 13 Z" fill="var(--cap)"/><path d="M17 1 L31 13 L17 13 Z" fill="var(--cap-dark)"/><rect x="1" y="12" width="32" height="2" rx="1" fill="var(--cap-dark)"/></svg>
<button class="board" type="button" aria-expanded="false" aria-controls="sign-menu" data-board data-autoclic>
<span class="board__body" aria-hidden="true" data-board-body>
<span class="board__face board__face--front"><span class="board__word">Menu</span><span class="shade" data-shade></span></span>
<span class="board__face board__face--back"><span class="board__word">Close</span><span class="shade" data-shade></span></span>
</span>
<span class="sr" data-name>Open the menu</span>
</button>
<ul class="arms" id="sign-menu" data-arms inert>
<li><a class="arm" href="#line-up" style="--paint: #d4532f; --ink: #fff6e6" data-arm><span class="arm__label">Line-up</span></a></li>
<li><a class="arm" href="#tickets" style="--paint: #e9a823; --ink: #2b1a0b" data-arm><span class="arm__label">Tickets</span></a></li>
<li><a class="arm" href="#camping" style="--paint: #2f6b4c; --ink: #fff6e6" data-arm><span class="arm__label">Camping</span></a></li>
<li><a class="arm" href="#food" style="--paint: #2a7896; --ink: #fff6e6" data-arm><span class="arm__label">Food & drink</span></a></li>
<li><a class="arm" href="#getting-here" style="--paint: #6d3f7c; --ink: #fff6e6" data-arm><span class="arm__label">Getting here</span></a></li>
</ul>
</div>
</div>
<p class="sr" aria-live="polite" data-live></p>
</nav>
</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.
39 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 signpost menu” from Animorio and fit it into my siteEvery board is an element with transform-style: preserve-3d and five flat slices inside: the painted face in front at translateZ(3.5 units), three slices of bare wood at -2.2, 0 and 2.2, and the back face turned round. Head-on only the face shows; as the board turns, the slices in between peek out one behind the other and make its thickness. The arrow shape is one clip-path shared by all the slices; the back of an arrow is turned with rotateX(180deg), so when the chosen arrow flips over its long side the words on the back read the right way up.
The post is a window with overflow: hidden, as tall as the script says, holding the whole length of wood pinned to its bottom: as the window grows, the wood comes down out of the board point first, like a telescopic pole. The length rides a damped spring (POLE_SPRING) that overshoots and comes back; when the post hits its stop, the SWAY swing rocks the whole scene with rotateZ from the top, on a very slow, lightly damped spring.
Every arrow has an angle round the post (90 degrees is folded edge-on behind the post, 0 is out) and turns with rotateY round the edge of the post, to the left or to the right (the sign flips for the left-hand arrows). There is no fixed delay: every frame the script checks where the end of the post is, and when it goes past the middle of an arrow it gives the arrow the speed FLING outwards. So the cascade really follows the post, even when it is closed halfway.
Each arrow's torsion spring (ARM_SPRING) is lightly damped, so the arrow overshoots and wobbles. On top of that every arrow feels how far its neighbours are off their rest (COUPLING): it is a chain of coupled oscillators, and the wobble runs up and down the post. The physics takes four small steps a frame, with the step capped at 1/30 of a second, and nothing that has not changed is redrawn.
The normal of every face is worked out from the rotateY and rotateX angles, and its light is the dot product with a light from the upper left (Lambert): a dark veil over the face takes that as its opacity. The pointer entering an arrow pushes it back in proportion to its speed (BRUSH); with a finger the push comes on the touch. Each arrow's speed drives the BNCE axis of Shantell Sans, a variable font whose letters bounce up and down.
| Name | File | Default | What it changes |
|---|---|---|---|
POLE_SPRING | script.js | [150, 0.42] | The post sliding out: how hard it pulls to its length, and how damped it is (1 = no bounce). |
ARM_SPRING | script.js | [210, 0.26] | The arrows' torsion springs round the post: stiffness and damping. |
FLING | script.js | 620 | How fast an arrow is flung out when the post reaches it, in degrees a second. |
COUPLING | script.js | 70 | How much of an arrow's wobble passes to the next ones through the post. |
BRUSH | script.js | 1 | How hard the pointer pushes an arrow it brushes past. |
SPIN | script.js | [130, 0.34] | The board's spin from Menu to Close: stiffness and damping. |
FOLD_STAGGER | script.js | 0.055 | The seconds between one arrow folding back and the next, when closing. |
SWAY | script.js | 1.4 | How far the whole sign sways when the post lands, in degrees. |
For the menu of an outdoor site: a festival, a campsite, a park, a mountain hut, a walking or cycling trail, a farm. From three to six short sections (a dozen letters at most), each with its own colour; with more the post gets too long for the screen.
The whole drawing scales to the width of the screen: at 390 pixels an arrow is about 155 long and the open sign fits without spilling over. A finger touching an arrow gives it the same push as the pointer brushing past, and the tap chooses it.
No spinning and no wobbling: the board changes face behind a short fade, and the post with its arrows appears or disappears already in place, fading. The arrows do not swing under the pointer and choosing does not flip them.
GSAP 3.15.0, Shantell Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 9.7 KB; the libraries: GSAP 28 KB.
Tested on 13 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.