Skip to content
animorio
IT
Back to the library

Spines on the shelf

Hover, 3DGSAP, CSS onlyMediumCompressed weight: Demo 7.2 KBGSAP 28 KBFreeDownload the zip

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.

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

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.

114 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 “Spines on the shelf” from Animorio and fit it into my site

What it does

On a paper-coloured ground there is a shelf: a thin black line with the edge of the board under it, and on it fourteen book spines drawn in outline, of different thicknesses and heights, side by side, each with its title running down the spine in narrow Anybody; some have two thin bands near the head and the foot. The last book, shorter, leans on its neighbour on a slant, balanced on one corner. When the page opens the board stretches out, the books are set down one after the other from the left with a little bounce, the last one arrives upright and then falls into its lean with a small knock against its neighbour; then the third book comes out by itself. When the pointer goes over a spine, the book rises a few pixels and tips towards the viewer, turning on its foot, in true perspective: the spine gets shorter and above it the edges of the pages appear, a band of thin lines; it goes a hair past the mark and settles. Its title turns orange and takes weight, and the two neighbours sway a little, as if they had felt the knock. Leaving it, the book goes back into the row with a little bounce. Going over the leaning book, instead, the book stands up and slides into the row against its neighbour; leaving it, it falls back into its lean and knocks against the neighbour. Under the shelf the title of the book in hand rolls in, large, with the author and the year in grey and the price on the right; at rest the line says Fourteen books on the shelf.

How it works

The books from a table

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

A book in 3D with CSS

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

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 springs and the neighbours

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.

The card under the shelf

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.

Values to change

NameFileDefaultWhat it changes
BOOKSscript.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.
CURRENCYscript.js'£'The sign written before the price.
TIPscript.js24How far a book tips towards you, in degrees.
LIFTscript.js10How far it rises as it tips, in pixels.
LEANscript.js14How far the last book leans, in degrees.
DEPTHscript.js150How deep the books are: the band of pages you see.
SPRINGscript.js1.8How much the book overshoots as it tips.
--accentstyle.css#ff5a1fThe colour of the title of the book in hand.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • With the perspective’s eye at the top of the shelf the head of every book showed, skewed differently on the right and on the left, and the shelf looked untidy: the eye sits a little below the middle, and the head only appears on the tipped book.
  • The leaning book, standing up on its corner, ended up upright far from the others: together with the rotation it moves back by height times the sine of the angle and slides into the row.
  • Measuring the titles before the typeface had loaded, long titles ran off the spine: the measure is taken again when document.fonts is ready.
  • On a phone, with all fourteen books, the titles came down to seven pixels: there books are taken off the end until they stay readable.

Libraries

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.

Testing

Tested on 19 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 animations