
The menu that opens from its button
Menus, Transitions, Text
Free
The code block of the docs of a small SDK for publishing posts, in the minimal style: hairline rules, greys and a single blue for the values. Pressing Wrap lines makes the long lines wrap live: the lines below make room, then the tail of every long line comes out from under the right edge, drops a row and slides into its indent, word after word, each on its own spring, lighter while it runs and fuller as it lands. The line numbers follow, and a hairline draws itself in the margin beside the rows of the same line. Copy puts the code on the clipboard and draws a tick.
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 code that wraps</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/recursive@5.3.0/full.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- a code block from the docs of a small publishing SDK, Slugline. Wrap lines bends the long lines live: the tail
of each one comes out from under the right edge, drops a row and slides into its hanging indent, word after
word, while the lines below make room and their numbers follow. Copy puts the code on the clipboard and
draws a tick -->
<section class="snippet" aria-label="Publish a post with the Slugline SDK" data-snippet data-autoclic>
<header class="snippet__bar">
<span class="file" data-file>publish.ts</span>
<div class="tools">
<button class="tool wrap" type="button" role="switch" aria-checked="false" data-wrap>
<svg class="wrap__icon" viewBox="0 0 20 20" aria-hidden="true">
<path class="wrap__edge" d="M15.5 3.5V16.5"/>
<path class="wrap__line" d="M3 7L19 7C19 7 19 7 19 7L19 7" data-wrap-line/>
<path class="wrap__head" d="M17 5L19 7L17 9" data-wrap-head/>
</svg>
<span class="tool__label" data-wrap-label>Wrap lines</span>
</button>
<button class="tool copy" type="button" data-copy>
<svg class="copy__icon" viewBox="0 0 20 20" aria-hidden="true">
<g data-sheets>
<rect x="7" y="7" width="9.5" height="9.5" rx="2"/>
<path d="M13 7V5.5a2 2 0 0 0-2-2H5.5a2 2 0 0 0-2 2V11a2 2 0 0 0 2 2H7"/>
</g>
<path class="copy__tick" pathLength="1" d="M4.5 10.4l3.6 3.6 7.6-7.8" data-tick/>
</svg>
<span class="copy__label"><span data-copy-label>Copy</span></span>
</button>
</div>
</header>
<div class="code" role="region" aria-label="publish.ts" tabindex="0" data-code>
<div class="code__gutter" aria-hidden="true" data-gutter></div>
<div class="code__view" data-view>
<div class="code__sheet" aria-hidden="true" data-sheet></div>
</div>
<pre class="sr" data-text></pre>
</div>
<p class="sr" aria-live="polite" data-live></p>
</section>
</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.
28 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 code that wraps” from Animorio and fit it into my siteEach line of the file is cut into words and spaces by a regex (comments, texts in quotes or backticks, figures, names, signs); a name is a word of the language if it is in a list, a function if a bracket follows, a property name if a dot comes before. Spaces do not become elements: they only count as columns. Recursive with its MONO axis at 1 is monospaced and keeps its width across weights and slants, so a single measure (60 zeros, getBoundingClientRect) gives the width of a character, and every word knows where it stands: column times width, row times height. The words are absolutely positioned spans, moved with a transform.
With Wrap lines on, a line longer than the columns of the box breaks at the latest possible place: after a space in the second half of the row, else after a comma or an opening bracket, else before a dot; spaces at the start of the new row are skipped. The rows after the first start at the line's indent plus HANG spaces (never past half the row). Off, each line stays on one row, the sheet is as wide as the longest line and the box scrolls sideways, with a fade on the edge (a mask-image with two animated @property values) saying there is more code.
On a change every word keeps where it is and is given its new place, plus two moments: when it starts going down and when it starts sliding. A damped spring for each axis (SPRING: stiffness and damping, 0.86 means a pixel too far and back) takes it there, in steps of at most 1/120 of a second and never more than 1/30 a frame. Pressing again halfway, the springs change their goal from where they are, with no jump; a box that changes width gives new goals too, and the words follow.
Wrapping, every line starts ROW_STAGGER after the one above, so the ones below make room first; the tail of a long line goes down with its line and a little later, LEAD seconds on, starts sliding left: the path turns the corner. In the tail the head word starts first and the others follow WORD_STAGGER apart. Going back the order is reversed: the tails slide right (the rightmost word in front), then rise, and only then the lines below come back up and the block gets shorter. The line numbers have their own spring and follow the first row of each line.
Every frame a word's speed takes up to THIN off its weight (Recursive's wght axis); when a travelling word gets within a pixel of its goal, for 0.42 seconds it takes up to LAND extra weight, on a sine arc. The font stays as wide, so nothing moves; font-variation-settings is written only when it changes. When nothing moves the loop stops.
Copy writes to the clipboard with navigator.clipboard, or else with a hidden field and execCommand, or else selects the text; the confirmation goes through aria-live, and the real code sits in a pre that screen readers read. Wrap lines is a button with role=switch and aria-checked, and also answers Alt+Z as editors do. A click from a script on the block (the library's preview) plays the whole round in a timeline: it wraps, copies and goes back as it was.
| Name | File | Default | What it changes |
|---|---|---|---|
CODE | script.js | ["// Publish a draft, then refresh every page that lists it", "import { createClient } from '@slugline/sdk';", …] | The code, one line of the file for each entry. Tabs become two spaces. |
START_WRAPPED | script.js | false | Whether the long lines start wrapped. |
HANG | script.js | 2 | How many spaces further in the rows of a wrapped line start. |
SPRING | script.js | [150, 0.86] | The spring every word moves on: how stiff and how damped (1 = no overshoot at all). |
ROW_STAGGER | script.js | 0.014 | The seconds between a line and the one below it. |
WORD_STAGGER | script.js | 0.01 | The seconds between one word and the next in the same tail. |
LEAD | script.js | 0.2 | How much earlier the drop starts than the slide: the bigger, the sharper the corner of the path. |
THIN | script.js | 150 | How much weight a word loses while it runs, on the wght axis. |
LAND | script.js | 170 | How much weight a word takes for a moment as it lands. |
COPIED | script.js | 1.6 | The seconds Copied stays before going back to Copy. |
For the documentation of an SDK, an API or a command-line tool, a product's install guide, the technical blog of a studio or a developer: wherever there are code samples with long lines to be read on a phone.
Under 480 pixels the code goes down to 12 pixels and the margin of the numbers narrows, so about 40 characters fit on a row: off, the code scrolls sideways under the finger; on, the lines wrap even two or three times, with the same springs and the same choreography. Under 360 pixels the file's name hides to leave room for the two controls. Taps do not wait for a double tap (touch-action manipulation), and nothing spills sideways.
The words go straight to their new place and the code comes back with a fade; the hairline in the margin appears without drawing itself, the Wrap lines icon changes without bending, Copy's tick and label change without moving, and the entrance is a single fade.
GSAP 3.15.0, Recursive (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 12 KB; the libraries: GSAP 28 KB.
Tested on 16 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.