Skip to content
animorio
IT
All components

The basket in lines

Carts, Text, TransitionsGSAP, CSS onlyAdvancedCompressed weight: Demo 14 KBGSAP 28 KBFreeDownload the zip

The small basket of a plain stationery shop, in the minimal style: four products set as lines of type, with the quantity, the price and a sign to take them away. Change a quantity and only the digits that change roll, the rightmost first, and the total recomposes itself digit by digit; take a product away and a vermilion hairline strikes it out, then its line folds shut like paper while the others rise on springs; under every new total the rule of the sum is drawn again. Undo unfolds it.

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 basket in lines</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>
  <main class="stage">
    <!-- the small basket of a plain stationery shop, set as lines of type: every product is a line with its price,
         its quantity and a sign to take it away. A quantity that changes rolls its figures and the total recomposes
         itself digit by digit; a product taken away is struck through with a hairline and its line folds shut like
         paper, while the lines under it rise on springs; the rule of the sum is drawn again under every new total -->
    <section class="cart" aria-labelledby="cart-title" data-cart data-autoclic>
      <header class="cart__head">
        <h2 class="cart__title" id="cart-title">Basket</h2>
        <div class="cart__side">
          <button class="undo" type="button" hidden data-undo>
            <svg class="undo__icon" viewBox="0 0 16 16" aria-hidden="true"><path d="M5.5 3.5 2.5 6.5l3 3"/><path d="M2.8 6.5h6.7a3.5 3.5 0 0 1 0 7H7"/></svg>
            <span class="undo__word">Undo</span>
            <span class="undo__time" aria-hidden="true" data-undo-time></span>
          </button>
          <p class="cart__count"><span class="roll" aria-hidden="true" data-count-n></span><span aria-hidden="true" data-count-word>items</span><span class="sr" data-count-sr></span></p>
        </div>
      </header>
      <span class="cart__rule" aria-hidden="true" data-head-rule></span>

      <div class="lines" data-lines>
        <ul class="lines__list" aria-label="Products" data-list></ul>
        <p class="lines__empty" aria-hidden="true" data-empty>Nothing in the basket yet.</p>
      </div>

      <div class="sum" data-sum>
        <div class="sum__rule" aria-hidden="true" data-sum-rule>
          <svg class="sum__plus" viewBox="0 0 10 10"><path d="M5 1.5v7M1.5 5h7"/></svg>
          <span class="sum__line" data-sum-line></span>
        </div>
        <p class="sum__total">
          <span class="sum__label">Total</span>
          <span class="sum__figure" aria-hidden="true" data-total-box><span class="sum__cur c" data-cur></span><span class="roll" data-total></span></span><span class="sr" data-total-sr></span>
        </p>
        <p class="sum__note">Delivery and taxes at the next step.</p>
      </div>

      <button class="go" type="button" data-go>
        <span class="go__fill" aria-hidden="true" data-go-fill></span>
        <span class="go__label" data-go-label>Checkout</span>
      </button>

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

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.

41 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 basket in lines” from Animorio and fit it into my site

What it does

On a white background, 440 pixels wide, the basket: Basket in narrow black, 5 items on the right, and a black rule under it. Then four lines divided by very thin rules: Dot grid notebook, Brass pencil, Fountain pen ink and Archive box, each with its size in grey under the name, the minus and plus signs with the quantity between them, the price and a small cross. At the bottom a tiny plus and the rule of the sum, Total with €77.50 large and narrow, a line about delivery and the black Checkout pill. On arrival the rule is drawn from the left, the lines rise one after the other and their figures roll in from nothing; then the total recomposes itself and its rule is drawn from the right. With plus or minus only the digits that change roll, up for a rise and down for a fall, the rightmost first and then the others, like a carry: while they run they narrow on the width axis, they land a pixel past their place and come back, and for a moment they take a touch of grade. If the total gains a digit (from €98.00 to €107.50) a new cell opens on the left, if it loses one the cell closes. The rule of the sum goes off to the left and is drawn again from the right, as wide as the new total. With the cross, or minus on a quantity of one, a vermilion hairline strikes the line out from left to right and the text turns grey; then the line folds in half like a strip of paper, its lower half a little darker, until it is zero tall, and the lines under it rise each on its own spring, the further ones a moment later. At the top Undo appears in vermilion, with a thread under it that shortens over five seconds: pressed, the line opens again pushing the others down and the hairline goes back. The pill, under the mouse, swells a little past its edges and its word widens on the width axis, with a small bounce; pressed, it squashes.

How it works

Digits as windows on a strip

Every digit of a figure is a cell as wide as one digit (Roboto Flex has tabular figures, all the same: the width is measured once with a probe) and 1.3 em tall, with overflow hidden and a mask that fades above and below. Inside it there is a strip: at rest one digit, when it changes the digits from the old one to the new one, in the way of the change. GSAP moves the strip with power3.out to one pixel past its place (the overshoot is in pixels, not a share of the run, so it is the same for one step or seven) and then back; at the end the strip goes back to a single digit.

The carry, from the right

The new figure is matched with the old one from the right, so units meet units and the decimal point stays put. For every position: the same digit does nothing, a different one rolls, CARRY seconds later for each place to the left; one position more opens its cell from zero width and its digit comes in from nothing, one less rolls away and its cell closes. A long way round (7 down to 8) shows only the last four digits of the road: the strip stays short and the figure calm.

The axes at work: width and grade

Every frame the speed of the strip (digits per second) narrows its digits on the wdth axis by up to NARROW, like a typographic blur; on landing a short tween takes the GRAD axis to 80 and back to zero. Grade thickens the strokes without changing the width, so the cells do not move a pixel while the digit takes weight. The axes live in the strip's font-variation-settings, starting from the width of its figure (the total is narrow, 78).

The hairline and the paper fold

Taking a product away is a timeline: an element 1.5 pixels tall grows with scaleX from the left across the name's line, then the line folds. Two copies of the line are made, each in a window half as tall: the top half turns on its top edge with rotateX(θ), the bottom one is moved (h/2)·cos θ down and (h/2)·sin θ towards the viewer and turns by −θ, so its bottom edge lands exactly at h·cos θ. The real line, hidden, counts for the layout as exactly h·cos θ; the half turned away from the light darkens a little with the sine of the angle. Undo folds it back the other way and the hairline withdraws.

Lines on springs, with contact

The lines are absolute and each one has a spring (SPRING, with steps of at most 1/120 of a second and never more than 1/30 a frame) that follows the sum of the heights above it; the further a line is from the one that changes, the softer its spring (RIPPLE), so they rise one after the other and settle with a pixel too many. A line never rides more than a pixel and a half into the one above: a line opening again pushes the others down instead of landing on them. The height of the list, and so the total and the pill, is on a spring too; when nothing moves the loop stops.

The sum, the pill, the keys and the preview

The rule of the sum is as wide as the new total, measured on a hidden copy: it goes off to the left and is drawn again from the right, and the plus beside it bounces. The Checkout pill has two springs, the swell (softer, it bounces) and the squash: the fill scales a few pixels past its edges and the word goes from wdth 100 to 124. Everything is real buttons; Delete takes the focused line away, Ctrl or Cmd with Z undoes, the focus goes to Undo and back to the line opened again, and an aria-live region reads the quantity and the total. A click from a script on the basket (detail 0, the library's preview) makes a round: two pluses, a line taken away, Undo, two minuses and the pill pressed.

Values to change

NameFileDefaultWhat it changes
ITEMSscript.js[['Dot grid notebook', 'A5 · 120 g paper', 18, 1], …]The products: name, the line under it, the price of one and how many.
CURRENCYscript.js€The sign before the prices.
MAX_QTYscript.js9The most of one product.
ROLLscript.js0.6The seconds a digit takes to roll to its new figure.
CARRYscript.js0.05The delay between a digit and the one on its left, like a carry.
NARROWscript.js0.3How much a digit narrows on the width axis while it runs fast (0, never).
STRIKEscript.js0.45The seconds of the hairline striking a product out.
FOLDscript.js0.6The seconds of the line folding shut.
SPRINGscript.js[300, 28]The spring of the lines rising: how stiff, and how much it is held back.
RIPPLEscript.js0.35How much later the lines further down answer (0, all together).
UNDO_TIMEscript.js5The seconds Undo stays after a product goes.

Try them in the Playground

When to use it

For the side basket or the basket page of a shop with few products and a lot of type: a stationery shop, a bookshop, a coffee or homeware shop, the till of a ticket site; also for any list with quantities and a total (a quote, a table order). It suits three to six short lines; colours and springs change in the variables.

On phones

Below 480 pixels the columns tighten (the basket is as wide as the screen less 32, 358 at 390), the name goes down to 15 pixels and ends with an ellipsis if it does not fit, the total to 38. Everything else is the same: the digits roll, the lines fold, the springs are the same. Taps do not wait for a double tap (touch-action manipulation) and on the pill a finger does what the mouse does: it swells and squashes it.

With reduced motion

No rolling digits: they change in place. Taking a product away the hairline fades in, the line fades out and the others take its place at once without sliding; Undo fades it back in. The rule of the sum changes width without being drawn again, the pill does not swell, Undo fades in and on opening the basket fades in.

Pitfalls

  • back.out's overshoot is a share of the run: a digit going seven steps overshot by four pixels, one going one step by half a pixel. Now the strip goes with power3.out to exactly one pixel past, counted on the cell's real height, and back.
  • With the rule of the way (down for a fall) a digit from 7 to 8 went nine steps, and a total falling from 107.50 to 98.00 became a tangle of half digits. Now a long way round shows only the last four digits of the road.
  • Narrowing the digits with wdth made them narrower and the cell, as wide as its content, shrank: the whole figure trembled. The cell has a fixed width measured once, and the axis changes only on the strip inside.
  • Opening a line again, the ones under it followed on springs and for a moment rode over it: now a line cannot go more than a pixel and a half into the one above (it takes its speed), and the folding line sits above the others.
  • The plus beside the rule of the sum turned 90 degrees and at 45 it was a cross, a multiplication sign: now it bounces on its scale.
  • Taking away a line with the focus inside it, the focus ended up on the page: it goes to Undo, and after Undo it comes back to the cross of the line opened again.

Libraries

GSAP 3.15.0, Roboto Flex (font variabile, con gli assi della larghezza, del peso e del grado) 5.3.0.

Compressed with gzip, the three demo files weigh 14 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