
The copy button
Buttons, Text, SVG, Physics
NewFree
In the minimal style: a concert setlist to put in order by dragging, one song per line as on ruled paper. Picked up, a song rises a pixel with the faintest shadow and takes weight; the others open up to make room, each on its own spring, and the space where it would go is a vermilion line that lengthens as the space opens and shortens as it closes. Let go, it lands on the line, which gives under it and settles, and the start times follow.
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 setlist on ruled lines</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- tonight's setlist, a list to put in order by dragging. Every song sits on a thin line, as on ruled paper. Picked
up, a song rises a pixel with the faintest shadow and takes weight; the others open up to make room on
springs, one after the other, and the space where it would land is a vermilion line that grows as the space
opens and shrinks as it closes. Put down, the song lands on that line, the line gives under it and settles.
The start times follow the order. Keys: Space picks up, the arrows move, Space puts down, Escape cancels.
On a phone: press and hold a song, then drag it -->
<section class="set" aria-labelledby="set-title" data-set data-autoclic>
<header class="set__head" data-head>
<h2 class="set__title" id="set-title">Tonight’s set</h2>
<p class="set__meta" data-meta></p>
</header>
<div class="sheet">
<span class="sheet__rule" aria-hidden="true" data-head-rule></span>
<ol class="songs" aria-label="Running order" aria-describedby="set-keys" data-list></ol>
<!-- the open spaces: one thin line for every place the song in hand could land, as long as the space is open -->
<svg class="gaps" aria-hidden="true" data-gaps></svg>
</div>
<p class="set__hint" aria-hidden="true" data-hint><span class="set__hint-mouse">Drag a song to change the order</span><span class="set__hint-touch">Press and hold a song, then drag it</span></p>
<p class="sr" id="set-keys">Press Space to pick a song up, the up and down arrows to move it, Space again to put it down, Escape to cancel.</p>
<p class="sr" aria-live="assertive" 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.
37 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 setlist on ruled lines” from Animorio and fit it into my siteEvery song has its y and its velocity, and every frame (in steps of 1/240 of a second, with the time held to 1/30) a spring takes it to its place: with a song in hand, the others skip the space where it would go. The further a song is from the one in hand, the softer its spring and the less it is held back in proportion, so the damping ratio stays the same and the choreography starts from the near ones.
The vermilion lines are not animated: every frame the script measures the space between the bottom of a song and the top of the next one, where the springs have really got to, and draws a line as long as that space is open, centred (on a curve, so that a space of a pixel draws nothing). So as the hand passes the lines lengthen and shorten by themselves, more than one at a time too.
The row follows the pointer on a stiff spring, with a little give past both ends; the stiller the hand, the more the lines pull it towards the space where it would go, so the vermilion line shows under it. The weight (wght axis) rises on a GSAP tween, the width (wdth axis) drops with the speed: font-variation-settings are written only when they change.
Let go, the song goes to its place on a softer spring; when it gets there it joins the order, its line comes back vermilion and fades into grey, and the line (an SVG path with a quadratic curve) gets a push: it is a damped string that gives and comes back, while its two neighbours get a smaller one. The lift and the weight go back to zero with back.out, the settle of a pixel.
The times are worked out again from the order there would be if the song were let go now, and only the figures that changed roll, from below if the time is later and from above if it is earlier. With the keys the arrows go from song to song; Space picks one up, the arrows move it, Space puts it down and Escape cancels, all told by an aria-live region. With a finger a song is taken with a long press, so a quick swipe still scrolls the page.
| Name | File | Default | What it changes |
|---|---|---|---|
SONGS | script.js | [['Glass Orchard', '4:21'], ['Copper Weather', '3:48'], …] | The songs in the order when the page opens: title and length. |
START | script.js | '21:00' | When the set starts: every song shows the time it begins. |
LIFT | script.js | 1 | How many pixels a song rises when it is picked up. |
HELD_WEIGHT | script.js | 640 | The weight of the song in hand (200 to 800). |
REST_WEIGHT | script.js | 430 | The weight of the songs on their lines (200 to 800). |
SPRING | script.js | [320, 28] | The spring of the songs that make room: how stiff, and how much it is held back. |
RIPPLE | script.js | 0.45 | How much later the songs further from the one in hand answer (0, all together). |
SQUEEZE | script.js | 0.06 | How much a running song narrows on the width axis, for every pixel a second. |
PLUCK | script.js | 2 | How many pixels the line gives under a song put down on it. |
LONG_PRESS | script.js | 0.32 | On a phone, how many seconds a finger holds a song before it lifts. |
For any list whose order matters and is decided by hand: the setlist of a concert or a night, a festival programme, the reading order of a newsletter, the priorities on a board, the stops of a trip, the courses of a dinner. It suits a light, empty column with six to ten short items; the times on the right can be swapped for lengths, dates or nothing.
Below 520 pixels the column takes the screen less 32 pixels, the lines are 47 tall and the titles a little smaller. With a finger a song is pressed and held: its line darkens at once and after a third of a second the song lifts, then it is dragged and the page does not scroll; a quick swipe, on the other hand, scrolls the page as always. The hint at the bottom says Press and hold a song, then drag it.
No springs, no growing lines and no strings: the song picked up only takes the shadow and the weight, the others jump straight to their places and the space where it would go already has its whole vermilion line. The figures of the times change without rolling and when the page opens everything fades in. In the preview the song goes from place to place one step at a time.
GSAP 3.15.0, Bricolage Grotesque (font variabile, con gli assi del peso, della larghezza e della dimensione ottica) 5.3.0.
Compressed with gzip, the three demo files weigh 11 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.