Skip to content
animorio
IT
Back to the library

The word that wraps

TextGSAP, CSS onlyAdvancedCompressed weight: Demo 9.3 KBGSAP 28 KBFreeDownload the zip

A narrow newspaper column between two thin hairlines, in the minimal style: the column slowly narrows and widens and the text is set again at every pixel. When a syllable of the long word no longer fits, it tips off the end of the line and lands on the line below with a spring, while a vermilion hyphen stays hanging in the margin and sways a little. With the pointer you move the hairlines by hand.

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 word that wraps</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/newsreader@5.3.0/opsz.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <!-- a newspaper column between two hairline guides: the script sets the article inside, piece by piece, and sets
         it again every time the column changes its measure -->
    <i class="guide" data-guide aria-hidden="true"></i>
    <i class="guide" data-guide aria-hidden="true"></i>
    <i class="dim" data-dim aria-hidden="true"></i>
    <i class="dim" data-dim aria-hidden="true"></i>
    <p class="read" data-read aria-hidden="true"><b data-chars>24</b> characters a line</p>
    <p class="mast" data-mast>Brinemoor</p>
    <p class="col" data-col></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 word that wraps” from Animorio and fit it into my site

What it does

On ivory paper two thin hairlines come down from the top and mark the edges of a column; at the top a horizontal line grows from the middle and carries the measure, «21 characters a line», with the masthead, Brinemoor, above it. The article arrives inside, one word after another: «The mayor called the old tide clock extraordinarily sensible.» The long word is already broken: «extraor-» at the end of a line, with the red hyphen hanging outside the text, and «dinarily» below. Then the column starts to narrow. Every time the hairline reaches a word, the word tips off the end of its line and lands at the start of the line below, thin, and takes on weight as it settles with a little squash; the words that stay slide to make room for it and the line below feels the hit. The lines are set again one after the other, from the top down. The long word breaks into syllables further and further back, «extraor-», «extra-», «ex-»: at every break the hyphen hooks on and sways as if hung on a nail, then comes to rest. The count of characters a line goes down with the column. Then the column opens all the way, the syllables climb back and the word is whole again; at last it comes back to the middle, the article lifts away and fades, the hairlines withdraw and it all starts again. Moving the mouse over the page (or dragging a finger on a phone) makes the hairlines follow the pointer and turn dark: the column is as wide as the pointer is far from the middle.

How it works

Every piece on its own

The text is written in TEXT with a vertical bar wherever a word may break (ex|tra|or|di|nar|ily). Every word without bars, and every syllable of the others, is a span placed with a transform, and every syllable that may break has its own hyphen, a span with the «-» character in the accent colour. The widths are measured once, with the typeface loaded and the optical size fixed (opsz equal to the type size, so the measures do not change with the weight of the animation).

Setting the column on every frame

On every frame the width of the column decides how the text runs: a word that does not fit breaks after the last syllable that does (the hyphen stays outside, hanging in the margin, so it does not count), and if not even the first fits, it moves to the next line whole. The result is a list of lines, one for each piece. To keep it from trembling when the column stands right on the edge, the old setting stays as long as it still fits within 2.5 pixels.

Who leaves, who slides, who lands

When the list changes, every piece is checked for where it was and where it goes. If it stays on its line, it gets the difference as an offset and goes back to zero with a spring. If it changes line, a copy leaves over the edge (to the right going down, to the left going up) and fades, and the real piece drops into its new place from above with a damped spring written as an ease (BOUNCE sets how far it passes the line), thinner (wght 230) and then at its own weight, with a squash and a small knock to the words beside it.

A wave, not a pile

When a word wraps, every line below is set again. Animated all together they piled up; now they keep time: each line starts a tenth of a second after the one above, and within a line first the words that go leave, then the ones that stay slide, then the new ones land, one word after the other. The syllables of one word travel together.

The hanging hyphen

The hyphen sits at the end of its syllable and turns around its left end, at a height measured on a canvas (the middle of the «-» character from the baseline). It is a damped pendulum worked out on every frame: when it hooks on it gets a push (SWING), and it also feels the acceleration of the syllable bouncing. So it sways by about ten degrees and comes to rest in less than a second.

Values to change

NameFileDefaultWhat it changes
TEXTscript.js'The mayor called the old tide clock ex|tra|or|di|nar|ily sensible.'The article. A vertical bar | marks where a word may break: that is where the hyphen appears. Short texts with a long word towards the end give the clearest falls.
NARROWscript.js5.4The narrowest column, in ems of the text. Keep it narrower than the long word, so that in the narrow column the word is always broken.
WIDEscript.js12.5The widest column, in ems. On a phone it stops before the edge of the screen.
DRIFTscript.js5.5The seconds the column takes to close: higher is slower, and the falls come one at a time.
BOUNCEscript.js0.4How far a landing syllable goes past its line before it settles: 0 stops dead, 1 bounces a lot.
SWINGscript.js1How much the hyphen sways when it hooks on: 0 keeps it still, 2 sways twice as much.
JUSTIFYscript.jsfalseWith true the lines run from one hairline to the other as in a newspaper (and the word spaces open up); with false they are ragged, set flush left.
SPEEDscript.js1The speed of the round: 2 is twice as fast, 0.5 half as fast.

Try them in the Playground

When to use it

For a blog, a magazine or a newspaper site, beside an article or at the top, when you want to show that the typography is looked after; for a type foundry or a design studio talking about measure and hyphenation; for the about page of a publisher. It works with short sentences and a single long word.

On phones

The same animation: the text is a little smaller and the widest column stops before the edge of the screen. Dragging a finger sideways across the page moves the hairlines; lifting it, the column goes back to its round. Vertical scrolling stays free.

With reduced motion

Nothing slides or falls: the column fades in at three widths, one after the other (middle, narrow, wide), with the text already set and the hyphen still in its place, and fades out between one width and the next. The pointer still moves the hairlines, but the lines are set again at once, without movement.

Pitfalls

  • A variable called top at the top of the script gave «Identifier 'top' has already been declared»: top is already window.top. It is called topY.
  • gsap.killTweensOf(piece) in the reset at the start of the round also killed the timeline's tweens on the same object, and the text never appeared. The reset only stops the properties of the falls (ox, ay, ao, lift, sq, th).
  • When a word wraps, every line below is set again: animated all together, exits and arrivals piled up and the column became a heap of words. It needs an order: line by line, and within a line first who leaves, then who slides, then who lands.
  • With the narrowest column at 6.6 em the long word (6.4 em) fitted whole, and the hyphen vanished exactly when the column was narrowest. NARROW has to stay below the width of the long word.
  • A column standing right on the edge of a line break trembled between two settings. The old setting stays as long as it still fits within 2.5 pixels (with a pointer trembling by one pixel it happens at once).
  • The syllables of one word, each sliding with its own offset, overlapped under a fast pointer: syllables that stay on the same line take the offset of the syllable before and slide as one piece.

Libraries

GSAP 3.15.0, Newsreader (font variabile, assi opsz e wght) 5.3.0.

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

Testing

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