Turn a page
One of the first ideas for the top of my portfolio was a book. Not a photo of one: an open book drawn in a few thin lines, with pages that lean towards your cursor and turn when you click, letting a word float off each time.
It's in the code of the very first version, and it's still in there now. It has never been on screen. By the time the first version went up I'd swapped it for something else, so the function that draws it looks for its canvas, doesn't find one, and quietly returns.
Eleven curves
Everything is drawn on one canvas, and every page is a single quadratic curve from the spine to its tip. A page's position is one number, t, where 0 is lying flat on the right and 1 is lying flat on the left. The tip sits on a half-ellipse above the spine, and the curve's control point is pushed out sideways by up to 14 units, so the page has a slight belly, most of all when it's standing straight up.
There are eleven of them: six fanned on the left, already read, and five on the right, still to come, each 0.022 apart. Under them are two curved lines for the covers and a short stroke for the spine. That's the whole book.
const tip = (t) => {
const a = Math.PI * t;
return { x: cx + Math.cos(a) * half, y: baseY - Math.sin(a) * lift };
};
Leaning in
Each page has a resting place and a little spring. When the pointer is over the book, every page's target shifts towards it, by up to 0.12, scaled by how upright that page is, so the pages near the middle lean more than the ones lying flat. The spring pulls 8% of the gap each frame and keeps 82% of its speed, which gives a soft overshoot, like paper that's been breathed on.
One extra page on the right rises and settles on its own, on a slow sine wave, so the book looks alive even if you never touch it.
Clicking sends a page across from right to left. It closes 5.5% of the remaining distance each frame (plus a small constant, so it actually arrives), and as it passes the top it lets go of a word that drifts up and fades: brand, story, demand, voice, culture, speed, in that order, round and round.
Why it was retired
The only explanation is a comment in the code: "book variant retired in favour of signal". The signal is a field of particles that drifts like noise until your cursor gets near, then pulls itself together into words: fifteen years of turning noise into signal. Side by side, that one is about the work, and the book is about books.
I still like turning the pages, though, so here it is, finally doing what it was made for.
Two small changes for this page. The original ran its spring once per animation frame, so it would have moved twice as fast on a 120Hz screen; here it steps at a fixed 60 times a second. And it was drawn in Hanken Grotesk, the portfolio's typeface at the time, where this uses the Inter that the rest of the lab is set in. With reduced motion the pages stay still and the words appear without drifting.
- Built
- July 2026
- Stack
- Canvas 2D, no libraries
- Lives at
- Nowhere, until now
- Source
setupBook()inportfolio.html