
The dash relief
WebGL, 3D, Hover
Free
In the minimal style: a shelf of a small bookshop, thin outlined spines side by side and the last book leaning on the others. The spine under the pointer tips towards you in 3D, as if hooked at the top by a finger, on a spring that overshoots by a hair: it rises, shows the edges of its pages and its title turns orange; the neighbours sway a little. The leaning book stands up straight and slides into the row; underneath, title, author and price roll in.
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>Spines on the shelf</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage" data-stage>
<header class="top">
<span class="top__name">Sorrel Books</span>
<span class="top__note">Second-hand poetry and essays</span>
</header>
<!-- one shelf of thin outlined spines. The spine under the pointer tips towards you, as if a finger hooked its top,
and shows the edges of its pages; its neighbours lean a hair into the gap. The last book leans on the others
and stands up when it is pointed at -->
<section class="case" aria-label="The shelf">
<div class="shelf" data-shelf></div>
<div class="board" aria-hidden="true"></div>
<div class="card" aria-live="polite">
<span class="card__mask"><span class="card__title" data-title>Fourteen books on the shelf</span></span>
<span class="card__mask"><span class="card__meta" data-meta>Point at a spine to take it out</span></span>
<span class="card__mask card__mask--price"><span class="card__price" data-price></span></span>
</div>
</section>
<p class="hint" data-hint>Point at a spine</p>
</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.
114 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 “Spines on the shelf” from Animorio and fit it into my siteThe books are a table (BOOKS): title, author, year, price, thickness and height in pixels, and whether the spine has the two bands. The shelf puts them in a row, overlapping by a pixel so the outlines do not double, and centres them; if there is not enough room, on a narrow screen it takes books off the end (the leaning book always stays) until the scale stops falling below 0.82, then scales everything. A title longer than its spine is narrowed on the wdth axis down to 52, then made smaller.
Every book is an element with transform-style preserve-3d and two faces: the spine, and above it the head of the book, a rectangle DEPTH pixels deep turned 90 degrees backwards, with a striped gradient for the page edges and backface-visibility hidden. The shelf has perspective with the eye a little below the middle: upright, the head cannot be seen; tipping the book forward with rotationX turns the head towards the viewer and it appears.
The last book turns on its bottom left corner (transformOrigin 0% 100%) by LEAN degrees and stands as far from its neighbour as its top corner moves: height times the sine of the angle, so it touches it. To stand it up GSAP brings the rotation to zero and x back by the same amount together, and the book slides into the row along its neighbour.
The book under the pointer goes to rotationX minus TIP and y minus LIFT with back.out (SPRING is how much it overshoots); on the way back it uses a livelier back.out for the little bounce. The two neighbours get a push of a degree and a half on rotationZ that dies away with elastic.out. The leaning book falls back with power2.in and two short tweens that make the knock against its neighbour.
At every change the title, author and year, and price roll out of their masks with yPercent, staggered. The book under the pointer is found by its place along the shelf (and the leaning one by all the room it takes), in a band a little taller than the books; a little past either end of the row, the book at that end counts. The arrow keys move along the shelf.
| Name | File | Default | What it changes |
|---|---|---|---|
BOOKS | script.js | [['The Salt Year', 'Ines Marrow', 1974, 14, 44, 262, true], …] | The books: title, author, year, price, thickness and height in pixels, two bands on the spine or not. The last one leans. |
CURRENCY | script.js | '£' | The sign written before the price. |
TIP | script.js | 24 | How far a book tips towards you, in degrees. |
LIFT | script.js | 10 | How far it rises as it tips, in pixels. |
LEAN | script.js | 14 | How far the last book leans, in degrees. |
DEPTH | script.js | 150 | How deep the books are: the band of pages you see. |
SPRING | script.js | 1.8 | How much the book overshoots as it tips. |
--accent | style.css | #ff5a1f | The colour of the title of the book in hand. |
For a bookshop, a publisher or a library, for the reading list page of a blog, for an archive of magazines, records or notebooks: whenever a row of titles is best seen edge-on. Changing BOOKS turns it into any series.
The same animations with adapted sizes: fewer books stay on the shelf, big enough to read the titles, plus the leaning one. Touching a spine brings the book out and it stays out, dragging the finger moves to the others, a touch away from the shelf puts it back.
Nothing tips and the neighbours do not sway: the book under the pointer rises slightly with a gentle change and its title turns orange; the leaning book stands up without bouncing. The card underneath changes with a fade and the page appears already set.
GSAP 3.15.0, Anybody (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.2 KB; the libraries: GSAP 28 KB.
Tested on 19 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.