Skip to content
animorio
IT
All components

The setlist on ruled lines

Lists, Physics, TextGSAP, CSS onlyAdvancedCompressed weight: Demo 11 KBGSAP 28 KBFreeDownload the zip

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.

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 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>

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.

37 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 setlist on ruled lines” from Animorio and fit it into my site

What it does

On a white background the title Tonight’s set, black, narrow and full, with 8 songs · 36 min in grey beside it; below, a black hairline and eight songs, one per line, each standing on a thin grey line as on ruled paper, with the time it starts in grey on the right: Glass Orchard at 21:00, Copper Weather at 21:04 and so on down to Northern Quiet. When the page opens the hairline draws itself from the left and then, line after line, each line is drawn and its song rises onto it, a pixel too high, and takes its weight. With the mouse over a song its line darkens. Picked up and dragged, the song rises a pixel on a white card with a barely visible shadow and gets fuller; the line it leaves turns vermilion. The others move out of its way, the near ones first and the far ones a moment later, and between two songs the space that opens has a vermilion line as long as the space is open: the one where the song would go grows from the middle, the one it has just left shortens until it is gone. Running words narrow a little on the width axis, the more the faster they go. When the hand stops, the song slides over the space, so the vermilion line shows under it. The times follow the order while it is dragged, and only the figures that change roll. Let go, the song lands on the vermilion line, the line gives under it like a taut string and settles, the lines nearby feel the knock, the weight comes back down with a settle and the vermilion fades into grey.

How it works

A field of springs

Every 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.

Lines from the real spaces

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 song in hand

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.

The landing

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.

Times, keys, touch

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.

Values to change

NameFileDefaultWhat it changes
SONGSscript.js[['Glass Orchard', '4:21'], ['Copper Weather', '3:48'], …]The songs in the order when the page opens: title and length.
STARTscript.js'21:00'When the set starts: every song shows the time it begins.
LIFTscript.js1How many pixels a song rises when it is picked up.
HELD_WEIGHTscript.js640The weight of the song in hand (200 to 800).
REST_WEIGHTscript.js430The weight of the songs on their lines (200 to 800).
SPRINGscript.js[320, 28]The spring of the songs that make room: how stiff, and how much it is held back.
RIPPLEscript.js0.45How much later the songs further from the one in hand answer (0, all together).
SQUEEZEscript.js0.06How much a running song narrows on the width axis, for every pixel a second.
PLUCKscript.js2How many pixels the line gives under a song put down on it.
LONG_PRESSscript.js0.32On a phone, how many seconds a finger holds a song before it lifts.

Try them in the Playground

When to use it

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.

On phones

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.

With reduced motion

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.

Pitfalls

  • The song in hand, on a white card, covered exactly the vermilion line of the space it would go to: the lines now pull it towards that space the more the hand stays still, so the line shows as soon as you stop to look.
  • Dragging far past the bottom, every song was far from the one in hand and their springs got so soft they took two seconds: the distance is measured from the nearest point inside the list, and the softness has a limit.
  • Spaces of a pixel or two, while the springs settle, drew vermilion dashes everywhere: the length of the line follows a curve and below 3 per cent it is not drawn.
  • Moving the focused song in the DOM loses the focus: it is put back on the song right after, and the move happens only on landing, when the keys no longer hold it.
  • With a finger, taking a song at the first touch stopped the page from scrolling: it is taken with a long press, and only then does a non-passive touchmove stop the scrolling.

Libraries

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.

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 components