Skip to content
animorio
IT
Back to the library

The word on the elastic line

Hover, Text, PhysicsGSAPMediumCompressed weight: Demo 8.3 KBGSAP 28 KBFreeDownload the zip

In the minimal style: a big word on a thin line, every letter tied to the line by an invisible rubber band. The pointer catches the letter it touches and pulls it out of the row, the neighbours follow a little, the letter thins out and blushes and the line bends under it. Too far and the band gives: the letter snaps back into the row with a hard knock and a little tremble.

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>Tensile</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- one word on one hairline: every letter is tied to the line by an invisible rubber band -->
  <main class="stage" data-stage>
    <svg class="lines" data-lines aria-hidden="true">
      <path class="line" data-line d="" />
    </svg>
    <h1 class="word" data-word aria-label="Tensile"></h1>
    <p class="hint" data-hint>Catch a letter and pull it off the line.</p>
    <p class="read" data-readout aria-hidden="true"><span class="read__label">Tension</span> <span class="read__win"><b class="read__value" data-read>slack</b></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.

19 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 word on the elastic line” from Animorio and fit it into my site

What it does

On a paper-coloured ground there is a thin grey line and, on it, the word Tensile, big, in a variable typeface. At the start the line draws itself from the middle outwards and the letters arrive from above one after another, faded and a little askew: each one hits the line with a hard knock, squashes for an instant (wider and heavier) and the line under it bends and quivers like a string. Passing the pointer over a letter catches it: moving away, the letter is pulled out of the row towards the pointer, always a little behind it because the band gets stiffer the longer it is; it leans towards the pull, gets narrower and lighter like stretched rubber and turns red, while the two neighbours follow it a little and the line rises in a soft bump and turns red too. Going further than a letter and a half away, the band gives: the letter drops back at once, hits the line that works as its floor, squashes, trembles for an instant with its neighbours and stands up straight, and the line keeps swinging a little. Moving onto another letter lets the first one go. Bottom right, small print gives the tension: «slack» at rest, the value from 0 to 1 while pulling, «snap» when the band gives. If nobody touches the page, an invisible hand plucks a letter now and then.

How it works

A still box and a free letter

Every letter is a box with its width at rest, measured once and then fixed in pixels, holding a second element with the real letter. The script moves and deforms only the inner one: so when a letter narrows or widens on the axes of the variable typeface (font-stretch and font-weight, driven by two CSS variables) the word does not reflow and the neighbours do not shift. The box is a centred flex, so a letter that widens spills out evenly on both sides.

The catch and the break

Every frame looks for the letter under the pointer, inside an oval as tall as the letter around its resting point: that is the caught letter, and a new catch lets the old one go. The target of the caught letter is the distance to the pointer times PULL, a little less as the distance grows (the band stiffens); the neighbours get the same pull times NEIGHBOURS once for every letter in between. When the pointer goes further than REACH letter heights from the resting point, the catch breaks.

Springs for every letter

Every letter has a position, a lean and a stretch, moved by springs with a frequency and a damping, in fixed steps of a two-hundred-and-fortieth of a second inside gsap.ticker. While it is pulled it uses a soft, nearly critical spring that chases the hand; let go, a hard spring (SNAP, in hertz) with little damping (TREMBLE), which is the knock. Below the line the letter finds a floor nine times stiffer than the band: it does not sink, it hits. At the moment of the knock the stretch gets a push backwards, so the letter squashes wide and heavy and comes back, and the lean gets a kick that makes the tremble.

The line that works as a string

The line is an SVG path redrawn every frame: two fixed ends and one point under every letter, joined by a smooth curve (Catmull-Rom turned into Bezier curves). Every point is a light, lightly damped spring that follows a share (LINE) of its letter's movement, so the line rises under the pulled letter and, when the letter hits, takes the blow and quivers like a string. The colour and thickness of the line and the colour of the letter come from color-mix with a tension variable, so the colours stay in :root.

Directing: the entrance, the reading and the invisible hand

The entrance is a GSAP timeline: the line draws itself with expo.out, then every letter, held up high and already stretched, is let go with a staggered delay and the same physics knocks it into the row. The tension reading changes word by rolling through a little window (back.out for «snap», with a shake of a few pixels). After IDLE seconds with no pointer a timeline moves an invisible hand: it slowly pulls a letter, holds it for a breath, gives a last tug and the band gives; a real pointer sends it away.

Values to change

NameFileDefaultWhat it changes
WORDscript.js'Tensile'The word on the line (up to 16 letters; a short one stays big).
PULLscript.js0.62How far the caught letter follows the pointer: 0.3 is a stiff band, 0.9 a loose one.
REACHscript.js1.25How far the pointer can go, in letter heights, before the band gives.
NEIGHBOURSscript.js0.36How much the neighbouring letters are dragged along with the caught one (0 = not at all).
SNAPscript.js6.5How hard the letter snaps back, in hertz: 3 is a soft rubber band, 12 a steel spring.
TREMBLEscript.js0.13How long the tremble lasts after the knock: 0.05 a long shiver, 0.6 almost none.
LINEscript.js0.34How much the line bends with the letters (0 = it stays straight and only changes colour).
THINscript.js1How much a stretched letter thins out on the width and weight axes of the typeface.
IDLEscript.js2.2After how many seconds without a pointer the invisible hand plucks a letter (0 = never).
--tautstyle.css#e0462aThe colour of tension, on the line and on the stretched letter.
--weightstyle.css640The weight of the word's typeface, from 100 to 900.
--widthstyle.css112The width of the word's typeface, in percent (from 60 to 140).

Try them in the Playground

When to use it

For a heading you can touch: the opening of a portfolio or a studio, a brand name in a landing page, the 404 page, the cover of a type project. It works with any short word.

On phones

The same physics with the sizes adapted: the word fills almost the whole width and the distance at which the band gives is measured in letter heights, so it works small too. You catch a letter with a finger and drag it; lifting the finger lets the band go. The hint changes to «Drag a letter off the line.» and hides if there is no room beside the tension reading.

With reduced motion

Nothing moves: the line and the letters fade in and stay still. The caught letter and the line only change colour, fading towards red the harder you pull, and fade back when the band gives.

Pitfalls

  • With the width of the typeface changed on the whole letter, a letter that thinned out pulled all the others along and the word danced: every letter's box has its width fixed in pixels and only the letter inside it deforms.
  • Let go with just a lightly damped spring, a letter pulled up came back down and went half a letter below the line, and the line made a huge wave: below the resting point there is a much harder floor, and the knock becomes sharp instead of a long bounce.
  • In the entrance the letters held up high pulled the line with them and the line made a bump before they even arrived: until a letter touches the line for the first time, the line does not follow it.
  • With every letter coloured by its own stretch, the neighbours turned brown: the red only goes to the last caught letter, the others take a fifth of it.
  • The tension reading went from «snap» to a small number and then to «slack», two changes in a row that looked like a flicker: after the break it goes straight back to «slack».
  • The GSAP transform on the tension reading (the shake) wiped out the translate that put it in place: the position is set with left and top, and the transform is left to GSAP.

Libraries

GSAP 3.15.0, Anybody (font variabile) 5.3.0.

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

Testing

Tested on 14 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