Skip to content
animorio
IT
All components

The seed catalogue

Books, 3D, Physics, WebGLWebGL, Canvas, GSAPAdvancedCompressed weight: Demo 27 KBGSAP 28 KBFreeDownload the zip

A seed company's spring catalogue, printed in four risograph inks, leafed through by taking its pages by the corner. The paper is drawn in WebGL and bends like the real thing: round a cone whose tip sits on the line of the spine, so the spine stays put, the paper never stretches and the corner you hold curls more than the rest. Let go, the page falls to the side it leans to, the air holds back its edge and the paper flutters as it lands; light, sheen and shadow come from the shape.

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>The seed catalogue</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/caprasimo@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- a seed catalogue printed in four risograph inks. The pages are drawn on a WebGL canvas: a page taken by a
         corner bends round a cone whose tip sits on the line of the spine, so the spine stays put and the paper never
         stretches; light, sheen and shadow come from the shape. The words below are the real pages: the script draws
         them on the paper, and a screen reader reads them -->
    <section class="catalogue" aria-label="Wrenfield Seed Co., spring catalogue" data-catalogue data-autoclic>
      <div class="book" tabindex="0" role="group" aria-roledescription="catalogue" aria-label="Wrenfield Seed Co., spring catalogue" data-book>
        <canvas class="book__paper" aria-hidden="true" data-paper></canvas>
        <canvas class="book__ghost" aria-hidden="true" data-ghost></canvas>
        <span class="book__ring" aria-hidden="true" data-ring></span>

        <div class="book__text" data-pages>
          <article data-art="cover" data-name="Cover">
            <p data-kicker>Spring 2027</p>
            <h2><span>Wrenfield</span> <span>Seed Co.</span></h2>
            <p data-text>Heirloom vegetables, herbs and cutting flowers.</p>
            <p data-text>Grown and saved on our own fields.</p>
          </article>

          <article data-art="note" data-name="From the field">
            <h2>From the field</h2>
            <p data-text>Every packet in here was grown on our farm, picked by hand and dried in the old barn. We sow what we sell, so we only sell what did well for us.</p>
            <p data-sign>Mara and Teo, growers</p>
            <h3>When to sow</h3>
            <ul>
              <li data-sow="3-4" data-pick="7-9">Tomatoes: sow in March and April, pick from July to September.</li>
              <li data-sow="5-6" data-pick="7-9">Beans: sow in May and June, pick from July to September.</li>
              <li data-sow="4-5" data-pick="9-10">Squash: sow in April and May, pick in September and October.</li>
              <li data-sow="3-6" data-pick="5-10">Herbs: sow from March to June, pick from May to October.</li>
              <li data-sow="4-5" data-pick="7-10">Flowers: sow in April and May, cut from July to October.</li>
            </ul>
          </article>

          <article data-art="tomatoes" data-name="Tomatoes">
            <p data-kicker>Tomatoes</p>
            <h2>Sun on the vine</h2>
            <ul>
              <li><b>Brandywine</b> <span>Pink beefsteak, rich and old fashioned.</span> <span data-days>85 days</span> <span data-price>$3.80</span></li>
              <li><b>Green Zebra</b> <span>Striped, sharp and very juicy.</span> <span data-days>75 days</span> <span data-price>$3.60</span></li>
              <li><b>San Marzano</b> <span>Long and meaty, the one for sauce.</span> <span data-days>80 days</span> <span data-price>$3.40</span></li>
            </ul>
          </article>

          <article data-art="beans" data-name="Beans and peas">
            <p data-kicker>Beans and peas</p>
            <h2>Up the poles</h2>
            <ul>
              <li><b>Borlotti</b> <span>Splashed pods, creamy beans.</span> <span data-days>65 days</span> <span data-price>$3.20</span></li>
              <li><b>Blue Lake</b> <span>A stringless green climber.</span> <span data-days>60 days</span> <span data-price>$2.90</span></li>
              <li><b>Scarlet Runner</b> <span>Red flowers first, then long pods.</span> <span data-days>70 days</span> <span data-price>$3.20</span></li>
            </ul>
          </article>

          <article data-art="squash" data-name="Squash">
            <p data-kicker>Squash</p>
            <h2>Keeps till spring</h2>
            <ul>
              <li><b>Musquée de Provence</b> <span>Deep ribs and sweet orange flesh.</span> <span data-days>120 days</span> <span data-price>$4.10</span></li>
              <li><b>Delicata</b> <span>Small and striped, no peeling.</span> <span data-days>100 days</span> <span data-price>$3.60</span></li>
              <li><b>Crown Prince</b> <span>Blue grey skin, keeps for months.</span> <span data-days>110 days</span> <span data-price>$3.90</span></li>
            </ul>
          </article>

          <article data-art="herbs" data-name="Herbs">
            <p data-kicker>Herbs</p>
            <h2>By the kitchen door</h2>
            <ul>
              <li><b>Genovese basil</b> <span>Big soft leaves for pesto.</span> <span data-days>60 days</span> <span data-price>$2.80</span></li>
              <li><b>Dill</b> <span>Feathery, with flowers for pickles.</span> <span data-days>55 days</span> <span data-price>$2.40</span></li>
              <li><b>Flat-leaf parsley</b> <span>Sow a little, and often.</span> <span data-days>75 days</span> <span data-price>$2.40</span></li>
            </ul>
          </article>

          <article data-art="flowers" data-name="Cutting flowers">
            <p data-kicker>Cutting flowers</p>
            <h2>A bucket a week</h2>
            <ul>
              <li><b>Zinnia</b> <span>Hot colours from July to the frost.</span> <span data-days>75 days</span> <span data-price>$3.20</span></li>
              <li><b>Cosmos</b> <span>Tall and airy, the more you cut.</span> <span data-days>90 days</span> <span data-price>$3.00</span></li>
              <li><b>Sweet pea</b> <span>Scented, sow in autumn or spring.</span> <span data-days>100 days</span> <span data-price>$3.40</span></li>
            </ul>
          </article>

          <article data-art="back" data-name="Back cover">
            <h2>Order by post or at the farm gate</h2>
            <p data-text>Packets leave the barn within two days.</p>
            <p data-text>Every order over $25 comes with a free packet of marigolds.</p>
            <p data-sign>Wrenfield Seed Co.</p>
          </article>
        </div>
      </div>

      <nav class="leaf" aria-label="Pages">
        <button class="leaf__btn leaf__btn--prev" 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="leaf__roll" data-where></span></p>
        <button class="leaf__btn leaf__btn--next" 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>

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.

108 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 “The seed catalogue” from Animorio and fit it into my site

What it does

On a white background the spring catalogue of the Wrenfield Seed Co., closed: a yellow cover printed on a risograph, with a red sun, a green ploughed field and a wren on a post, against the light. As soon as it arrives, the bottom corner of the cover curls up and drops back, as if to say it can be leafed through. Taking a page by the corner and dragging it, the paper bends under the hand: near the spine it stays down, towards the corner it rises and rolls, and the spot you took stays under the finger; taken at the bottom the bend runs diagonally, taken halfway down the edge it becomes a cylinder, and moving the corner up or down straightens or tilts the bend. As it rises the page catches the light or falls into shade with its slope, a soft sheen runs over the curve, its shadow falls on the pages below, darker where the paper is low, and in the air the print of its back shows through. Let go past the middle, or flicked, the page falls over by its own weight, its edge held back by the air, and the paper flutters as it lands; before the middle it falls back. The cover is card, stiffer than the pages. Open, the catalogue slides over with the spine in the middle; inside a letter from the growers with the sowing calendar, then tomatoes, beans, squash, herbs and cutting flowers, each with its drawing in four inks, three varieties, the days and the price; in the fold of the middle pages lie the two staples. With the mouse near the edge of a page the corner turns down like a dog-ear. Below, the arrows and the names of the open pages, which slide in the direction of the page. On a phone it turns one page at a time.

How it works

A cone with its tip on the spine

The page is a grid of 34 by 26 points on the flat sheet. Bent, every point lies on a line from the tip of a cone set on the line of the spine, past the top or bottom edge: the spine is one of those lines, so it does not move, and every point keeps its distance from the tip, so the paper never stretches (it is Hong, Card and Chen's model for electronic books, generalised). Going round the tip, the direction of the lines traces a curve on a sphere: it is built in steps, turning the direction of travel by as much as the bend wants (spread with a smoothstep over part of the page) and then walking on along the great circle; the first direction is the angle round the spine. Normals included, it is 40 rotations a page.

Where you take it

The cone's tip comes close to the corner you take: taken at the corner it sits a fifth of a page away, and the bend is tight and diagonal; taken halfway down the edge it goes very far, and the cone becomes a cylinder. The whole move is one number p from 0 to 1: at first it is nearly all bend (the corner lifts), then the page turns, and at the end it lies flat. To keep the spot you took under the finger, at every move the script works out where it would land on the screen, perspective included, for 40 values of p and takes the right one; moving the corner up or down brings the tip closer or further.

Weight, air and flutter

The hand pulls the page with a stiff spring, so when let go the page has the hand's speed. Free, it turns round the spine by its own weight (a torque that goes with the cosine of the angle and changes sign past the middle), slowed by the air linearly and quadratically, and lands with a little bounce; the bend is a second spring (FLUTTER) pulled towards −AIR times the speed, so the edge lags while it falls and flutters as it lands. The page cannot bend into the pile: the bend stays between −angle and 180° − angle. On release, where it will land is simulated ahead, and the words below change at once. The arrows are a pretend hand that lifts the bottom corner inside the same physics and lets the page go past the top.

Printed in four inks

The real pages are the articles in the HTML, hidden from sight and read by screen readers: the script reads them and prints them once onto 1024 canvases, in units of 300 by 414. Each ink (yellow, green, red, blue) is a layer of its own, pitted where the drum runs dry with a grain pattern, laid on the paper with multiply and shifted by a hair, like a risograph out of register: red on yellow makes the squash orange, green on yellow the leaf green, blue on yellow the dark green of the title. Type: Caprasimo for titles and names, Bricolage Grotesque for the rest.

Light, sheen and shadow

In WebGL every page has two faces (gl_FrontFacing picks the print) and the light is worked out on the normal: Lambert, normalised so a page lying flat shows the right colours, a little light coming through from behind, a sheen only where the curve faces the light more than a flat page, the fold at the spine and the edge. In the air the paper lets the print of its back show through, reversed. The shadow: the pages in the air are cast along the light into a texture 256 wide, darker where they are low (MAX blending), blurred in two passes and read by the lying pages and the table; under the top page of each pile the edges of three sheets peek out.

One page at a time, keys and the preview

Under 640 pixels each page sits on a sheet of its own, with a plain back and the print showing through; the turned page leaves the frame fading, and the one before is brought back by dragging from the left third. Closed, the catalogue sits in the middle, and goes back there only once every page has crossed the spine. Arrows, Page Up and Down, Home and End; aria-live says the open pages. A click from a script (the library's preview) turns the next page and, at the back cover, brings all the pages back in a fan.

Values to change

NameFileDefaultWhat it changes
TURNscript.js0.5The seconds the arrows' hand takes to carry a page over the top.
BENDscript.js1.15How far a page curls when taken by a corner, in radians.
PEEKscript.js1.5How far the corner curls when the mouse comes near it, in radians.
AIRscript.js0.1How much the air holds back the edge of a falling page.
FLUTTERscript.js[130, 6]The paper's spring: stiffness and damping (lower, more flutter as it lands).
GRAVITYscript.js24How quickly a page let go falls to the side it leans to.
COVERscript.js2.2How many times stiffer the cover is than the pages.
LIGHTscript.js[-0.36, 0.3, 1]Where the light comes from: left or right, up or down, and its height.
SHADOWscript.js0.42How dark the shadow of a lifted page is.
DEPTHscript.js2200The perspective in pixels: smaller brings a lifted page closer to you.

Try them in the Playground

When to use it

For the catalogue of a nursery or a seed company, a magazine, a brochure, a lookbook, a restaurant's menu, a recipe book, the yearbook of a club or a school, a wedding booklet: anything printed that is worth leafing through.

On phones

Under 640 pixels the catalogue shows one page at a time, up to 360 pixels wide: the finger takes the page and turns it towards the spine on the left, and a third of the way is enough for it to fall; the page before is brought back by dragging from the left third to the right. The catalogue lets the page scroll vertically (touch-action pan-y) and only takes sideways gestures. The corners that turn down under the mouse are not there on a phone.

With reduced motion

Pages turn at once, with the arrows, the keys, a tap or a sideways swipe: the old pages dissolve over the new ones. No bending under the hand, no corners under the mouse, no entrance, and the catalogue changes place without sliding.

Pitfalls

  • The arrows' hand was a GSAP tween while the physics ran in steps capped at 1/30 of a second: with slow frames the hand reached the top before the page, which fell back and then jumped to the other side. Now the hand moves inside the physics, and on release the speed is raised until the landing forecast gives the right side.
  • In WebGL 1 mipmaps need textures with power-of-two sides: the pages are printed squeezed into 1024 squares (units of 300 by 414) and the grid's coordinates stretch them back.
  • A corner lifted less than 30 degrees can hardly be seen from above: for the dog-ear under the mouse the paper rolls up to about 85 degrees in the last band, with the cone's tip half a page from the corner; with the tip closer the whole top edge rolled.
  • The sheets under the top one, shifted by a pixel to show the thickness, showed scraps of their print: now they are bare paper, and three at most.
  • Moving the closed catalogue back to the middle as soon as the last arrow was pressed slid the left pile out of the frame while the pages were still coming back: the catalogue slides only once every page has crossed the spine, and never under a hand holding a page.
  • The shadow of a standing page, with a low light, ran off the canvas and was cut by its edge: a higher light, a shadow that fades with height, and a last 30-pixel fade at the canvas edges.
  • The back's print showing through a lying page looked like dirt, and on the yellow cover like a reversed title: it shows only in the air, and hardly at all through the cover, which is card.

Libraries

GSAP 3.15.0, Caprasimo 5.3.0, Bricolage Grotesque (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 27 KB; the libraries: GSAP 28 KB.

Testing

Tested on 6 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 components