
Words that melt into each other
Text, Scroll, SVG
NewFree
A minimal-style text animation: a thin line runs across electrocardiogram paper and beats like a real heart, at 72 beats a minute; every spike falls where a letter belongs and the letter grows out of the spike, thin, then settles and gains weight. With the word written, the heart keeps beating under it; moving the pointer quickens the beat.
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 written by a heartbeat</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/inter-tight@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage" data-stage aria-label="Steady, a heart clinic. A heartbeat trace writes the word heart.">
<header class="top">
<span class="brand">Steady</span>
<span class="what">Heart clinic</span>
</header>
<!-- the trace and the letters: one SVG, built by the script -->
<svg class="scene" data-scene aria-hidden="true">
<defs data-defs></defs>
<path class="trace" data-trace d="" />
<path class="trace trace--beat" data-beat d="" />
<g data-letters></g>
</svg>
<h1 class="sr-only" data-word>heart</h1>
<footer class="bottom" aria-hidden="true">
<span class="rate"><b data-rate>72</b> bpm</span>
<span class="hint" data-hint>Move to quicken the beat</span>
</footer>
</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.
18 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 written by a heartbeat” from Animorio and fit it into my siteThe shape of a beat is a function of the distance from its spike, measured in beats: the P and T waves are two cosine bells, Q, R and S three straight strokes as in real traces. The R spike is as tall as the letter it writes times SPIKE; the other waves are fractions of the cap height.
The middle of each letter is measured on a canvas in the same face (variable Inter Tight), with measureText of pieces of the word, so it keeps the kerning. The width of one beat is the mean distance between two letters, and the line runs at the speed that puts one beat between two letters: at 72 beats a minute, a beat every 0.83 seconds.
The line is a path redrawn on every frame with one point per pixel, from the left up to the head of the trace; the height at each point is the sum of the beats already written, each times its envelope. A second path, in vermilion, redraws only the last stretch: the beat being drawn, then the running pulse.
Every letter is an SVG text cut by a rectangle (clipPath) that rises from the line when the spike reaches its middle. Then the weight goes from LIGHT to HEAVY, the letter lifts a pixel and comes back with elastic.out, and the envelope of its beat drops to 0.16: the spike becomes a small blip under the letter.
All the direction is one repeating timeline: the run of the trace, the letters, six calm beats and the way back. The rhythm is the timeline's timeScale: the pointer pushes it towards FAST over BPM, and when it stops it slowly goes back to one. So a faster heart is just a faster timeline, and the line, the letters and the number always stay together.
| Name | File | Default | What it changes |
|---|---|---|---|
WORD | script.js | 'heart' | The word the trace writes, one letter per beat (up to 8 letters). |
BPM | script.js | 72 | The resting heart rate, in beats per minute. |
FAST | script.js | 128 | The heart rate the pointer pushes it to. |
SPIKE | script.js | 1.06 | How tall the spike is, compared with the letter it writes. |
LIGHT | script.js | 160 | The weight of a letter as it grows out of the spike (100 to 900). |
HEAVY | script.js | 640 | The weight it settles into (100 to 900). |
BEATS | script.js | 6 | How many calm beats before the word is written again. |
For the headline or the wordmark of a clinic, a health or fitness app, a prevention campaign, a cardiology site; also for an opening that has to say ‘alive’ without a picture, or for the name of a product that measures something.
The same animation with the sizes adapted: the font size is chosen so the word fits the width and the spike the height of the screen, and the line stays 16 pixels from the edges. A tap quickens the heart.
Nothing moves: the word is already written on the trace, with the small blips under the letters, and the beat count stands still.
GSAP 3.15.0, Inter Tight (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 6.2 KB; the libraries: GSAP 28 KB.
Tested on 22 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.