
The dash relief
WebGL, 3D, Hover
Free
Four cards with the letters of the word FILM: each letter is a solid turning slowly around two axes, and its outline is filled with the footage of its category, flat, as if the letter were a hole in the screen. Only the outline changes, the picture inside stays put and keeps playing.
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>Letters full of film</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/schibsted-grotesk@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
<script type="importmap">
{ "imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.178.0/build/three.module.min.js"
} }
</script>
</head>
<body>
<!-- the reels of a made-up film studio, one per letter of its word: each letter is a solid that turns slowly in 3D,
and its outline is filled with that reel's footage, flat, as if the letter were a hole cut in a screen -->
<main class="sala">
<header class="sala__testa">
<p class="sala__etichetta">Mango Pictures</p>
<h1 class="sala__titolo">Four reels, one word.</h1>
</header>
<div class="griglia" data-griglia>
<canvas class="griglia__tela" data-tela aria-hidden="true"></canvas>
<a class="carta" href="#" data-carta data-lettera="F" aria-label="Fashion, 12 films">
<span class="carta__lettera" data-lettera-box><canvas class="carta__film" data-film aria-hidden="true"></canvas></span>
<span class="carta__riga"><span>Fashion</span><span class="carta__numero">(12)</span></span>
</a>
<a class="carta" href="#" data-carta data-lettera="I" aria-label="Illustration, 21 films">
<span class="carta__lettera" data-lettera-box><canvas class="carta__film" data-film aria-hidden="true"></canvas></span>
<span class="carta__riga"><span>Illustration</span><span class="carta__numero">(21)</span></span>
</a>
<a class="carta" href="#" data-carta data-lettera="L" aria-label="Live, 5 films">
<span class="carta__lettera" data-lettera-box><canvas class="carta__film" data-film aria-hidden="true"></canvas></span>
<span class="carta__riga"><span>Live</span><span class="carta__numero">(5)</span></span>
</a>
<a class="carta" href="#" data-carta data-lettera="M" aria-label="Music videos, 9 films">
<span class="carta__lettera" data-lettera-box><canvas class="carta__film" data-film aria-hidden="true"></canvas></span>
<span class="carta__riga"><span>Music videos</span><span class="carta__numero">(9)</span></span>
</a>
</div>
</main>
<script type="module" 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.
23 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 “Letters full of film” from Animorio and fit it into my siteEach letter is drawn on a 32 by 32 square as a list of points, with a round hole in the I and a rounded corner in the L. With Three.js it becomes an extruded shape 8 thick, with a small bevel, centred on the origin. The same points also make a flat SVG mask for when WebGL is missing.
The camera is orthographic and √768 wide, the furthest a 32-unit letter can reach from its centre while it turns: so however it is turned, the letter never touches the edges of the card. Every frame the letter starts from zero and turns first about y and then about x, by angles that grow 0.0008 and 0.00082 radians a millisecond.
The letter’s shader lights nothing: it reads the footage at the screen pixel, gl_FragCoord minus the corner of the card, divided by its size. That is why the picture does not turn with the letter and the solid only shows in its outline. An optional value, SHADE, adds a little light on the faces.
A single WebGL canvas lies behind the whole grid; for each card the script measures its square, sets viewport and scissor there and draws its scene. In WebGL the y axis starts at the bottom, so the card is measured from the bottom of the grid. The loop only runs while the grid is on screen.
Each film is painted by the script on a 384-pixel canvas: stripes and gradients for the sunset, added radial gradients for the patches, faded triangles for the beams, sine waves for the waves. It is repainted thirty times a second and each time becomes its letter’s texture. With the pointer over a card, a spring brings the speed to four times and the footage zoom to 1.18.
| Name | File | Default | What it changes |
|---|---|---|---|
SPEED | script.js | [0.0008, 0.00082] | How fast a letter turns around its two axes, in radians a millisecond (as on the site). |
HOVER | script.js | 4 | How many times faster a letter turns with the pointer over it. |
ZOOM | script.js | 1.18 | How much closer the footage comes with the pointer over it. |
SCALE | script.js | 1 | How big the letter is in its card (1 = it never touches the edges). |
DEPTH | script.js | 8 | How thick the letters are (a letter is 32 wide). |
SHADE | script.js | 0 | A little light on the faces (0 = flat footage, as on the site). |
FPS | script.js | 30 | How many times a second the footage is repainted. |
For the categories of a portfolio, the sections of a video archive or the letters of a brand that also work as windows on the work: wherever each entry has footage to show and a letter to give it.
The cards sit two to a row and the letters turn the same way; with a finger the letter speeds up and the footage comes closer for as long as the card is held down.
No 3D and no movement: each card shows a still frame of its footage inside the flat outline of the letter.
Three.js 0.178.0, Schibsted Grotesk (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.7 KB; the libraries: Three.js 174 KB.
Tested on 6 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.