
The glass word
WebGL, 3D, Scroll, Text
Free
A paper ribbon closed with half a twist, a Möbius strip, in the minimal style: the word «INSIDE» runs slowly round it and after one lap comes back in front on the other face, where it reads «OUTSIDE» in the accent colour. Moving the pointer across it (or the wheel, or a finger) makes the ribbon run faster the way the hand goes, on a spring; let go and it slows down, goes past its pace by a whisker and settles.
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 ribbon with one side</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.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>
<!-- a thin paper ribbon closed with half a twist, a Moebius strip: it has one side and one edge. A word printed on
it runs round and round; after one lap it comes back on the other face, where a second word waits in the
accent. The script draws the ribbon and the letters on the canvas -->
<main class="stage" data-stage>
<canvas class="canvas" data-canvas aria-hidden="true"></canvas>
<h1 class="sr" data-sr>Inside, outside: a ribbon with one side.</h1>
<p class="hint" data-hint>Move across the ribbon</p>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<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.
14 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 ribbon with one side” from Animorio and fit it into my siteThe line along the middle of the ribbon is a circle on the floor; across it the ribbon turns by half a turn while it goes round once: the direction of the width is cos(u/2) upwards plus sin(u/2) outwards. After one lap the same paper is upside down and faces in. The mesh runs along the ribbon twice (u from 0 to 4π): the first lap is one face of the paper, the second the other, each drawn from its own side only (FrontSide). So every point is drawn once per face, and the same formula gives the normals for the light too.
One canvas holds both words: the first in the red channel, the second in the green one, on the same stretch of paper. The canvas covers only the stretch where the word sits (a copy of half a lap), so every pixel goes to the letters; on the ribbon the paper is not square, and the letters are drawn squeezing the x axis by the right factor. Every letter has its own state (how visible, how heavy, how far above its place) and is drawn on its own at its weight of the variable typeface Archivo; the positions are measured on the whole word, to keep the kerning.
In the fragment, T = u − flow says which point of the print is there: as the flow grows, the print slides along the ribbon without touching the geometry. The lap (T modulo 4π) picks the channel and the colour: ink on the first face, accent on the other. The canvas is read with textureGrad and the derivatives of T, which do not jump where one copy ends and the next begins. The ticks and the line of the edge are drawn in the shader with fwidth: they stay one pixel wide, and when the ribbon turns edge-on the edge becomes a thin line by itself.
The speed of the hand (how many page widths the pointer covers in a second, smoothed and fading by itself) is added to the pace of the ribbon; the real speed chases it on a damped spring, integrated in steps of 1/240 of a second. BOUNCE sets the damping: at 0 it stops without passing its pace, at 1 it passes it and comes back. The ring leans as much as the speed is away from its pace, on a lightly damped spring that makes it sway as it straightens; the weight of the letters grows with the same distance, and the canvas is redrawn only when the weight changes by at least 4.
A GSAP timeline reveals the paper along two laps (a uniform that cuts the ribbon where u passes the value), turns the ring by a quarter with a back.out and grows it from 94% with a light elastic. The letters arrive with three tweens staggered by 0.07 s: the fade, the drop with a back.out and the weight from 200 to the chosen one. Then the pace rises from zero with a power2.inOut. The loop of every frame sits in the GSAP ticker, so the bench can slow it down and stop it.
| Name | File | Default | What it changes |
|---|---|---|---|
FRONT_WORD | script.js | 'INSIDE' | The word on the right side of the ribbon, in ink. |
BACK_WORD | script.js | 'OUTSIDE' | The word that comes round on the other face, in the accent colour. |
LAP | script.js | 12 | How many seconds a word takes to go once round the ribbon, at rest. |
PUSH | script.js | 1.6 | How much the pointer, the wheel and a finger make the ribbon run: 0 not at all. |
BOUNCE | script.js | 0.4 | How far the speed goes past its pace when you let go: 0 not at all, 1 a lot. |
WEIGHT | script.js | 480 | The weight of the letters at rest, from 200 to 800; running they get heavier. |
BAND | script.js | 0.44 | The width of the ribbon, as a share of the radius of the ring. |
TILT | script.js | 24 | How much from above you look at the ring, in degrees. |
For the opening of a portfolio, a studio or a brand that plays on two opposite words (inside and outside, before and after, day and night): the ribbon holds them together on a single side. Also for the page of an event or an exhibition with a title of one or two words, or as an object to look at halfway down a long page.
The same ring, sized to fit nine tenths of the width; a finger dragged across makes the ribbon run like the pointer, and letting go it settles. The hint at the bottom says «Drag» instead of «Move».
Nothing turns and nothing slides: the ribbon fades in already drawn, with «INSIDE» in front and «OUTSIDE» at the back. Every four seconds it fades out and comes back showing the other face in front.
Three.js 0.178.0, GSAP 3.15.0, Archivo (font variabile, assi wdth e wght) 5.3.0.
Compressed with gzip, the three demo files weigh 8.7 KB; the libraries: GSAP 28 KB, Three.js 174 KB.
Tested on 15 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.