Skip to content
animorio
IT
Back to the library

The knock that runs through the sentence

Physics, TextGSAPAdvancedCompressed weight: Demo 8.4 KBGSAP 28 KBFreeDownload the zip

In the minimal style, with real physics: a sentence where every letter is a weight tied to its neighbours by springs, closed between two thin walls. A wall knocks and a compression wave runs along the sentence like sound through air, bounces off the other wall and comes back, weaker every time: where it passes the letters get narrower, heavier and blue on the axes of the variable typeface, and below a thin trace draws the pressure.

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>Hall acoustics</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/full.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- the whole room is the button: a click knocks the sentence from the nearer end; a letter can be pulled and let go -->
  <main class="stage" data-stage tabindex="0" role="button" aria-label="A sentence made of letters on springs. Press to knock it from one end and watch the push travel along it.">
    <header class="top">
      <span class="top__brand">Hall</span>
      <span class="top__note">Acoustics for rooms that carry a voice</span>
    </header>

    <!-- the sentence: the script splits it into letters, each one a weight on a spring between its neighbours -->
    <h1 class="line" data-line>a push, passed along</h1>

    <svg class="scope" data-svg aria-hidden="true">
      <path class="wall" data-wall-l d="" />
      <path class="wall" data-wall-r d="" />
      <path class="axis" data-axis d="" />
      <path class="marks" data-marks d="" />
      <path class="trace" data-trace d="" />
    </svg>

    <p class="hint" data-hint>Click near an end to knock the sentence, or pull a letter.</p>
    <p class="read" data-readout><span class="read__label">Compression</span> <b class="read__value" data-read>0%</b></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.

16 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 knock that runs through the sentence” from Animorio and fit it into my site

What it does

A warm white page, at the top the name of an invented acoustics studio, Hall. In the middle, large, the sentence a push, passed along: the letters rise into place one after another with a hair of overshoot, then two thin walls draw themselves at the ends of the sentence, and below a dotted line with a mark under every letter. The left wall lights up in blue and knocks, going in sharply and coming back slowly: the first letters squeeze together, the knock passes to the next ones and a band of squeezed letters runs along the sentence. Where it passes the letters turn narrow and heavy on the width and weight axes of the typeface, and the more squeezed they are, the bluer; behind it, where the springs stretch, they get a little wider and lighter. Below, a thin line draws the pressure letter by letter and you see the bump travel. The wave hits the right wall, comes back, passes again, lower every time, until the sentence is still. A few seconds later the right wall knocks, then the left one again. Bottom right you read the strongest compression of the moment. A click knocks from the nearer wall; a letter can be taken with the mouse or a finger and pulled sideways, and let go it sends two waves, one each way.

How it works

A uniform medium made of letters

The sentence is split into letters, each in a span the script places around its own centre. Every letter has a mass in proportion to its width and every spring between two letters is stiffer the shorter it is: so, as in a uniform material, the wave runs at the same speed everywhere, and that speed is the width of the sentence over CROSS seconds. Two more springs tie the first and the last letter to the walls.

The wall that knocks

The knock is not an animation of the letters: it is the wall that moves, going in on half a cosine in a short time and coming out eight times more slowly, and the wall's motion pulls the first spring. The knock lasts as long as the wave takes to cross five letters: shorter, the springs between single letters crumbled it into ripples (a lattice of springs disperses waves only a few steps long).

The step and the damping

The physics runs in fixed steps of a twelve-hundredth of a second inside gsap.ticker, and a frame's time never goes over a thirtieth of a second. The air takes speed away so the wave dies in about ECHOES crossings; a little friction inside the springs (in proportion to the difference in speed between neighbours) calms the fine shiver without touching the big wave. When everything is still the sentence falls asleep and is no longer redrawn.

The compression in the type

For every letter the compression is one minus the stretch of its two springs. Squeezed, the letter narrows on the wdth axis and gains weight on wght (font-variation-settings of Roboto Flex) and turns blue with gsap.utils.interpolate; pulled, it widens and gets lighter. The weight grows less than the width it loses: with too much weight the squeezed letters touched. The trace below passes through every letter's compression on a Catmull-Rom curve.

The loop on its own and the hand

A gsap.delayedCall makes a wall knock every EVERY seconds, one and then the other; a click knocks at once from the nearer wall and puts the loop back in step. A letter that is taken follows the pointer sideways, driven, and pulls on the springs; let go, it sends one wave each way. Every knock starts from the still sentence (what is left of the one before, a pixel or two, is let go), so the loop always comes back the same.

Values to change

NameFileDefaultWhat it changes
CROSSscript.js1.1How many seconds the knock takes to run from one end of the sentence to the other.
KNOCKscript.js1How hard the wall knocks: 0.5 is a tap, 1.6 is a slam.
ECHOESscript.js3About how many times the knock crosses the sentence before it dies down.
SQUEEZEscript.js1How much the letters answer on the width and weight axes (0 = not at all).
EVERYscript.js4.5How many seconds between two knocks when the page is left alone, one wall and then the other.
--accentstyle.css#2b4cffThe colour of the wall that knocks and of the most squeezed letters.
--weightstyle.css380The weight of the sentence’s typeface at rest, from 100 to 900.

Try them in the Playground

When to use it

For a sentence that should let you feel something passed from hand to hand: an acoustics studio, a music label, a podcast, the page of a delivery service or of a referral scheme, the title of a landing page that explains how something spreads. It works with any one-line sentence, up to forty characters.

On phones

The same physics: the sentence takes almost the whole width and the knock is always five letters long, so the wave reads the same. A tap knocks from the nearer wall, a letter is pulled with a finger.

With reduced motion

Nothing moves: the sentence fades in. A click fades it out and back in at the moment the wave is halfway, worked out silently (squeezed letters in blue, the trace with its bump), and a little later it comes back to rest, again in a fade.

Pitfalls

  • With a short knock (a tenth of a second) the wave was a letter and a half long and the lattice of springs dispersed it: after one crossing only ripples of a few pixels were left. The knock now lasts as long as five letters, and the bump reaches the other end whole.
  • The wall that went in and out at the same speed sent a compression followed by an equal pull: the letters behind the wave became hairline thin. Now it comes out eight times more slowly, and the pull is a light tail.
  • With the weight growing a lot (up to 1000) the squeezed letters got wider faster than they came closer, and the s, e and d of passed overlapped: now the width drops more and the weight less.
  • In reduced motion the picture of the wave halfway was drawn with the walls at rest, while the wall was still in: the last letter came out stretched and the g turned into a thread. The picture now carries the walls along too.
  • The card's video stops when the picture stays the same with no GSAP scheduled: while the sentence moves a gsap.delayedCall is always waiting, and the next knock is a delayedCall too.

Libraries

GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.

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

Testing

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