
The copy button
Buttons, Text, SVG, Physics
NewFree
A size picker in the minimal style where the width of the letters is the size: XS narrow, XL wide, on the wdth axis of a variable face. The size chosen widens a little more and takes weight while a hairline vermilion frame catches up with it on two springs, one side after the other; underneath, the measures change word by word and a sold-out size is struck through by a line that draws itself.
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 size picker</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/anybody@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- the size picker of a clothes shop, in the minimal style: five real radio buttons, XS to XL, where the width of
the letters is the size. Each size is set on the width axis of a variable face, from condensed to extended;
the one chosen widens a little more and takes weight while a hairline frame catches up with it on two springs,
one per side. The line under it says the measures and changes word by word. A sold-out size is struck through
by a thin line that draws itself. The frame, the strike and the ruler are one SVG drawn by the script -->
<form class="size" data-size onsubmit="return false">
<fieldset class="size__set" data-set data-autoclic>
<legend class="size__legend">Size</legend>
<p class="size__head" aria-hidden="true" data-head></p>
<div class="size__row" data-row>
<svg class="size__lines" aria-hidden="true" data-lines>
<path class="size__ruler" data-ruler/>
<path class="size__strike" pathLength="1" data-strike/>
<path class="size__frame" pathLength="1" data-frame/>
</svg>
</div>
<p class="size__line" aria-hidden="true" data-line></p>
<p class="size__status" aria-live="polite" data-status></p>
</fieldset>
</form>
</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.
41 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 size picker” from Animorio and fit it into my siteThe sizes are set in Anybody, a variable face whose wdth axis goes from 50 (extra compressed) to 150 (extra expanded). The script gives every size a value along the scale, from NARROW for the smallest to WIDE for the largest, and writes it in font-variation-settings together with the weight: so the row itself says how big each size is. Choosing adds GROW to the width and goes from LIGHT to BOLD, one step too far and back with elastic.out.
While the letters change width the cells change size and move: the script measures the chosen cell on every frame (offsetLeft and offsetWidth) and the frame gets there on two damped springs, one per side, integrated in steps of 1/240 of a second with the time step capped at 1/30. The side it is heading for has the quicker spring, the other is 36 per cent slower: the frame stretches and then closes up, and a damping SPRING[1] under 1 gives the one-pixel overshoot. Stretched wider than its cell it thins by a few tenths of a pixel, like a rubber band.
The frame, the strike of the sold-out size and the ruler are three paths of one SVG over the row, redrawn from the cells’ measures. Frame and strike have pathLength 1 and stroke-dasharray 1 1, so they draw themselves with a single number (stroke-dashoffset from 1 to 0) whatever their length. The loop runs on GSAP’s ticker only while something moves: once the springs are still and no tween is running it takes itself off.
The two lines of text are made of slots, one per word, as wide as the word. On a change the words are compared one by one: the same ones stay still, in the others the old letters leave one after the other and the new ones come in with back.out, from below if the size grows and from above if it shrinks, while the slot changes width with power3.inOut. The words start 30 milliseconds apart.
Under every size there is a real radio button: the arrow keys move from one size to the next and the sold-out one, with its radio disabled, is skipped by itself; a screen reader reads “Extra small, sold out” and an aria-live region says the measures. The disabled radio does not hear the pointer (pointer-events: none), so its label can notice the pointer or a tap and have the strike drawn again. A click from a script on the row (the library’s preview) takes one step of a tour: a size up, a size down, the sold-out one, the largest and back to M.
| Name | File | Default | What it changes |
|---|---|---|---|
SIZES | script.js | [['XS', 'Extra small', 84, 66, false], ['S', 'Small', 90, 68, true], …] | The sizes: letters, name, chest and length in cm, and whether it is in stock. |
START | script.js | 2 | The size chosen when the page opens (if it is sold out, the first one in stock). |
NARROW | script.js | 54 | The width (wdth axis) of the smallest size: 50 is the narrowest. |
WIDE | script.js | 136 | The width of the largest size: 150 is the widest. |
GROW | script.js | 12 | How much wider the letters of the size chosen get. |
LIGHT | script.js | 300 | The weight of the sizes not chosen (100 to 900). |
BOLD | script.js | 760 | The weight of the size chosen. |
SPRING | script.js | [24, 0.78] | The frame’s springs: how quick and how damped (under 1 they go a hair too far and come back). |
FIT | script.js | 'Fits true to size' | The end of the line of measures. |
On a garment’s page in a clothes shop (T-shirts, jumpers, jackets, shoes sized in letters), in the order form for the T-shirts of an event or a team, in the configurator of a product that comes in several sizes: wherever the size chosen must show at once and the measures must change with it.
The same animation with the sizes adapted: the script measures the row and shrinks the type just enough for it to fit the screen with every size, frame and ruler included. A touch stands in for hover: pressing a size its letters widen a little and squash, letting go they come back. Tapping the sold-out size the strike draws itself again and the line says so for a couple of seconds.
Nothing moves across: the sizes fade in already in place, choosing one its width and weight change at once, the frame fades out and back in round the new one without travelling, and the words of the line change with a fade instead of rolling.
GSAP 3.15.0, Anybody (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 8.6 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.