Skip to content
animorio
IT
Back to the library

The title on the steamy mirror

Text, ImagesCanvas, GSAPAdvancedCompressed weight: Demo 18 KBGSAP 28 KBFreeDownload the zip

A bathroom mirror fogs up as steam rises and an invisible finger writes the title on it: the stroke wipes the glass and shows the reflected room sharp, beads of water gather at the edges and the heavier ones run down leaving clear lines. Then the condensation comes back and wipes it all away. The pointer over the mirror wipes a soft patch.

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 title on the steamy mirror</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/familjen-grotesk@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="scena" data-scene>
    <!-- the title, for screen readers: the script keeps it in step with the phrase written in the steam -->
    <h1 class="leggibile" data-reader>Breathe in. Fogline bath rituals</h1>
    <!-- the bathroom: the tiles, the mirror, the room it reflects, the steam, the writing and the drops are all painted on this canvas -->
    <canvas class="bagno" data-bath aria-hidden="true"></canvas>
    <p class="nota" data-hint><span class="nota__mouse">Move over the mirror to wipe it</span><span class="nota__dito">Touch the mirror to wipe it</span></p>
  </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.

34 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 title on the steamy mirror” from Animorio and fit it into my site

What it does

A wall of sage glazed tiles, each one a slightly different shade with its own glint; in the middle an arched mirror with a brass frame and below it a marble shelf with the bottles of an invented cosmetics brand, Fogline. In the mirror you see the room behind us: a clay wall with a niche (folded towels, a candle, a vase), a pendant lamp that is on, a wooden ladder with a towel, a white bathtub and a plant. Steam rises from below in soft puffs and the mirror fogs up from the bottom upwards, with a wavy edge: the room turns blurred and milky, covered in tiny droplets. Then a finger you cannot see writes «Breathe in» in the condensation, letter by letter, and under it, smaller and quicker, «Fogline bath rituals»: wherever it passes, the glass is clean again and behind the letters the room is sharp. Beads of water gather along the edges of the stroke; after a while the heavier ones run down in jerks, stop, run on, swallow the beads they meet and leave a clear line and a few tiny drops behind them. The condensation slowly comes back: in patches first, then as a veil of droplets, and the words disappear. The finger writes the second phrase, «Glow slowly», which fogs over too; the steam stops, the mirror clears from top to bottom and it all starts again. Moving the pointer (or a finger, on a phone) over the mirror wipes a soft patch, which then fogs over again from its rim to its centre.

How it works

Two rooms: sharp and fogged

The reflected room is drawn once on a canvas as big as the glass: wall, niche, lamp, ladder, bathtub, plant. The fogged version is made from it: the same picture shrunk 14 times and enlarged again (a blur that works in every browser, even where ctx.filter is missing), with a milky veil on top, thicker at the bottom, and thousands of tiny droplets, each a dot of shade with a dot of light above it. On every frame the sharp room is drawn and the fogged one on top, cut out by a mask.

The mask of the condensation

The mask says where there is condensation. The climbing edge is a small texture (an eighth of the size), opaque below and transparent above with a wavy blend: enlarged it turns soft, and a tween moves it up. Then destination-out takes away the canvas of the strokes wiped by the finger, the circles of the drops (clear water: they show the room sharp) and the pointer's patch. Finally the fogged version is cut to the mask with destination-in.

The finger and the drops

The letters are a single-stroke alphabet: every letter is the path a finger would follow, with a bit of a hand in it (every letter slightly tilted, raised or lowered, the line leaning forward). A tween takes the distance travelled from zero to the length of all the strokes, pauses between strokes included; on every update the new piece is drawn in white on the strokes canvas and drops are born on both sides. After a wait the heavier ones run down in jerks: they run, catch, run again, swallow the drops they touch and leave a clear line on the same canvas.

The condensation coming back and the patch

Nothing is redrawn to erase: a tween brings the condensation from zero to one over the strokes, while a blotchy texture takes a little of the strokes away on every frame, so the steam creeps back in patches. Meanwhile the tiny droplets come back inside the strokes first, then the veil. The pointer's patch is a grid of numbers (a cell every 9 pixels): the pointer raises them with a soft falloff, time lowers them again, and the grid becomes a small picture enlarged onto the mask.

Direction

The whole round is one timeline with repeat: -1: the steam rising and the mirror fogging up, one phrase written, the rest with the drops running, the condensation coming back, the next phrase, then the mirror clearing. The tweens only move numbers (steam, height of the condensation, how fogged it is, how far the condensation has come back); the drawing is done by gsap.ticker, so the workbench can slow down and stop everything. The phrases, the line below, the finger's speed, the thickness of the condensation, the drops and the patch are values at the top of the script.

Values to change

NameFileDefaultWhat it changes
TITLEscript.js['Breathe in', 'Glow slowly']The phrases written in the condensation, one after another. The letters are single-stroke capitals; long phrases wrap by themselves.
SUBTITLEscript.js'Fogline bath rituals'The smaller line written under every phrase (empty = no line).
WRITE_SPEEDscript.js1How fast the finger writes: 2 is twice as fast, 0.5 half as fast.
FOGscript.js1How thick the condensation is: 0.5 is a light veil that lets the room show, 1 hides it almost completely.
DROPSscript.js1How many drops gather at the edges of the strokes and how many run down (0 = a clean stroke, no drops).
HALOscript.js1How big the patch wiped by the pointer is (0 = the pointer does not wipe).
RESTscript.js2.6How many seconds the written phrase stays before the condensation covers it again.

Try them in the Playground

When to use it

For the opening of a spa, a hammam, a cosmetics or bath products brand, for a welcome page or a message that should feel handwritten and fleeting. It works with short phrases: two or three words read best.

On phones

The same animation with the sizes adapted: the mirror is narrower and taller, the title wraps, the drops and the finger keep their proportions. A finger on the screen wipes the patch like the pointer.

With reduced motion

Nothing moves: no rising steam, the condensation fades in, the phrase fades in already written with its drops standing still, then the condensation fades back over it; at the end the mirror clears with a fade.

Pitfalls

  • Behind the letters there was a bright window: once wiped, the room was as light as the condensation and half the letters vanished. The reflected room must sit a few shades below the veil where the writing goes: a clay wall, a dark niche, no window.
  • Filling the condensation by adding a light veil on every frame stops short of full (with 8 bits the addition rounds to zero and a pale haze stays). The condensation does not build up: the mask is redrawn whole on every frame from a few numbers, and only the wiped strokes live on a canvas, which erases itself.
  • With too many heavy drops the title looked like it was bleeding in a horror film: only two drops in a hundred run, and they start at different times.
  • The catalogue video stops when nothing else is scheduled: with a story made of timelines handing over to each other the round never ended. One timeline with repeat: -1 tells the workbench how long a whole round lasts.
  • The edge of the condensation drawn at full size came out as straight as a ruler: the texture is small and enlarged, and the column by column blend makes the waves.

Libraries

GSAP 3.15.0, Familjen Grotesk (font variabile) 5.3.0.

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

Testing

Tested on 11 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 animations