
Glyphs that turn to look
Hover, Text, 3D
NewFree
In the minimal style: a stack of very thin sheets in 3D, seen edge on, with a letter printed in the corner of each sheet. Closed, only the edges of the sheets show, fine lines and one vermilion; the pointer, or a finger, turns the stack to three quarters and fans it open like a deck of cards, each sheet on its own spring, until the uncovered letters read as a word.
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 word in the fanned sheets</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage" data-stage>
<!-- the word people read; the sheets below are only its picture -->
<h1 class="sr" data-read>Sheaf</h1>
<!-- a stack of very thin sheets seen from three quarters, one letter on each. Closed and turned edge on, only the
edges of the sheets show, one of them in the accent colour; across the page the pointer (or a finger) turns
the stack towards you and fans it open like a deck of cards, until the letters read as a word -->
<div class="scene" aria-hidden="true" data-scene>
<div class="deck" data-deck></div>
</div>
<!-- the same thing for the keyboard: a slider that opens and closes the fan -->
<div class="handle" role="slider" tabindex="0" aria-label="Fan the sheets" aria-valuemin="0" aria-valuemax="100" aria-valuenow="100" data-handle></div>
<p class="note" aria-hidden="true">
<span class="note__hint" data-hint>Move across the page</span>
<span class="note__rule"></span>
<span class="note__deg" data-deg>0°</span>
</p>
<!-- an invisible letter, to measure how wide each one is on the width axis -->
<div class="probe" aria-hidden="true" data-probe></div>
</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.
15 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 word in the fanned sheets” from Animorio and fit it into my siteEvery letter of the word is a sheet: a div with transform-style: preserve-3d inside a deck that has the perspective, set apart from the others by GAP pixels on translateZ. The thickness of a sheet is a second div one and a half pixels wide, turned by 90 degrees with rotateY on the left edge: when the whole deck is turned by 90 degrees the faces disappear edge on and only these edges are left, close lines with a vermilion one (the sheet at the back of the stack). The whole deck turns with rotateY from 90 degrees to TURN and tilts by a few degrees with rotateX, so you look at it a little from above.
Every sheet turns in its own plane with rotateZ, and the transform-origin is a point outside the sheet, below its foot (PIVOT heights away): so the sheets open like a deck held in a hand, in a soft arc. The angle of sheet i is (i − middle) times FAN divided by the number of sheets minus one, multiplied by how open that sheet is. The size of the sheets is worked out by turning the four corners of every sheet round the pin: the open fan has to fit the page, on the computer and on the phone.
The pointer does not move the sheets: it says where the stack should be, from 0 (closed edge on) to 1 (open). First the stack turns towards you (up to 0.55), then the fan opens (from 0.3): closing, it goes the other way round. Every sheet follows its target with a damped spring worked out in small steps of 1/240 of a second; the front sheets have a stiffer spring than the back ones, so the fan opens and closes in a wave. BOUNCE lowers the damping: at the normal value every sheet goes one pixel past and back. When a spring is still it stops for good, so the browser stops redrawing and the letters come back sharp.
The letter sits in the top left corner of every sheet, in the strip that the sheet above leaves uncovered. That strip is worked out: the left edge of the sheet above, turned round the pin by the difference between the two angles, where it crosses the foot of the letter. With the fan open, a binary search on the wdth axis of Archivo, from 62 to 125, finds the width that fills the strip for every letter; on every frame the letter takes the share of that width (and of the weight, from 300 to WEIGHT) that matches how open its strip is. If the widest letter does not fit even at its narrowest, all of them get smaller.
The opening is a GSAP timeline: the edges draw with scaleY from the top, one after the other, the vermilion one last, with back.out going a hair past; the faces appear, and a tween takes the stack from 0 to 1 while the springs follow. Then the pointer is in charge: its horizontal position, between 15 and 70 per cent of the page, is the opening, and the vertical one tilts the stack by a few degrees. A finger is in charge only while it touches; when the mouse leaves or the finger lifts, a tween brings the stack back open. For the keyboard there is a role=slider: the arrows open and close by quarters, Home and End go to the ends.
| Name | File | Default | What it changes |
|---|---|---|---|
WORD | script.js | 'Sheaf' | The word: one sheet for every letter, from 2 to 9 letters. Spaces are left out. |
FAN | script.js | 40 | How far the fan opens, in degrees, from the first sheet to the last. The wider it opens, the more room the letters have. |
TURN | script.js | 30 | How far the open stack stays turned, in degrees: 0 is straight on, 60 very much at an angle. |
GAP | script.js | 5 | The space between one sheet and the next, in pixels: it decides how airy the stack looks edge on. |
WEIGHT | script.js | 720 | The weight of a letter once its strip is open, from 300 to 900; covered, it weighs 300. |
BOUNCE | script.js | 0.35 | How far the sheets go past their place before they settle: 0 not at all, 1 a small bounce. |
SPEED | script.js | 1 | The speed of the springs and of the opening: 2 is twice as fast, 0.5 half as fast. |
For the opening headline of a stationer, a bookbinder or a print shop, an archive, a paper magazine or a graphic design studio, where the word is also an object to leaf through; also for a short brand name on a landing page, or for a portfolio introduced by a single word. It works with words of four to seven letters.
The same animation: the open fan takes more than eight tenths of the width of the screen, the sheets and the letters are measured on it, and the stack opens and closes by dragging a finger across the page; once the finger lifts, it goes back open.
Nothing turns and nothing opens: the fan fades in already open, at three quarters, with the word reading; the pointer does not move it and the line at the foot is not there.
GSAP 3.15.0, Archivo (font variabile, assi wdth e wght) 5.3.0.
Compressed with gzip, the three demo files weigh 8.0 KB; the libraries: GSAP 28 KB.
Tested on 16 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.