Skip to content
animorio
IT
All components

The weight knob

Dials, Physics, TextGSAPAdvancedCompressed weight: Demo 10 KBGSAP 28 KBFreeDownload the zip

In the minimal style: the font weight knob of a design app's type panel, a ring of hairline ticks and a vermilion index. Turned, the word above it changes weight live from 100 to 900 and the figure beside it, in tabular figures, never jitters; at every hundred the knob holds for an instant and clicks, and flung it coasts on until it comes to rest on a tick. The ticks are as thick as the font's stems at that weight, measured on the font itself.

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 weight knob</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/opsz.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/inter-tight@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the weight knob of a design app's type panel: a ring of hairline ticks and an index. Turned round, flung, with
         the wheel or with the keys, it sets the weight of the word above it live from 100 to 900, and clicks at every
         hundred. The ticks of the ring are as thick as the font's own stems at their weight. The knob is drawn by the
         script -->
    <section class="weight" aria-label="Font weight" data-weight data-autoclic>
      <div class="specimen" aria-hidden="true" data-specimen>
        <span class="guide" data-guide="x"></span>
        <span class="guide" data-guide="base"></span>
        <p class="specimen__line" data-line><span class="specimen__word" data-word>Handgloves</span><span class="specimen__probe" data-probe></span></p>
      </div>

      <div class="control">
        <div class="knob" role="slider" tabindex="0" aria-labelledby="weight-label" aria-valuemin="100" aria-valuemax="900" aria-valuenow="400" aria-valuetext="400, Regular" data-knob>
          <svg class="knob__svg" viewBox="-100 -100 200 200" aria-hidden="true" data-svg></svg>
        </div>
        <div class="read" aria-hidden="true">
          <p class="read__label" id="weight-label">Weight</p>
          <p class="read__value" data-value>400</p>
          <p class="read__name"><span class="read__roll" data-name>Regular</span></p>
        </div>
      </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>

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.

21 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 weight knob” from Animorio and fit it into my site

What it does

On a black background the word Handgloves, the test word of type designers, in Fraunces, sitting on two hairlines, the baseline and the x-height. Below it, a knob: a ring of ticks over three hundred degrees, one every 25 units of weight and a longer, lighter one at every hundred, and inside a dark face with a hairline edge and a vermilion index. The ticks are not all alike: on the left, towards 100, they are hairs; on the right, towards 900, solid bars, because each one is as thick as the stem of the letter l at that weight. Beside it, Weight, the big figure in tabular figures and the name of the weight (Thin, Light, Regular, Bold, Black…). It turns by dragging round with the mouse or a finger: the word takes weight live, the figure changes without jittering, the index thickens with the word. At every hundred the knob is pulled into the notch and held there for an instant, then the hand tears it out: the click. The hundred it reaches stretches out with a small bounce and lights up vermilion, the index gives a little kick, the name of the weight lights up. Flung, the knob carries on by itself, slows down and comes to rest on a hundred, a pixel past and back; let go slowly, it rests on the nearest tick. Past 100 and 900 it gives only a little, as against a stop. The wheel, the arrows, Page up and down, Home and End work too; a double click puts it back to Regular.

How it works

The stems measured on the font

As soon as Fraunces is in, the script draws the letter l at 200 pixels on a hidden canvas, at every hundred from 100 to 900, and reads one row of pixels across the middle of the stem: adding up the coverage of each pixel, half-covered ones too, it finds the stem's thickness in ems. From those nine measures, interpolated in straight lines, come the thickness of every tick of the scale and that of the index, which changes live with the weight. If the font does not draw (the measures do not grow with the weight) a guess stays in place.

The hand on a spring, the hundreds as wells

Under the finger the angle is measured with atan2 round the middle and the difference, brought between −180 and 180, is added up; each degree is worth 800 / SWEEP units of weight. The knob does not follow the hand directly: it is pulled by a stiff spring, damped on the hand's speed, and every hundred is a well 16 units wide with a force of −DETENT · s · (1 − (s/16)²)². Coming in, the knob is sucked in, the figure stops on 500, and moves on only once the hand is far enough ahead: a real click, with no animation written by hand. The sums run in steps of 2 milliseconds on GSAP's ticker, with the time step held to 1/30 of a second.

The fling that knows where it stops

Let go faster than 250 units a second, the point where the FRICTION would stop it (v + w / FRICTION) is worked out at once and the nearest hundred becomes the target. The run is an exponential v(t) = T + (v₀ − T)·e^(−kt) with k = w / (T − v₀): it starts at exactly the speed of the hand and ends exactly on the tick. For the last 12 units a slightly springy spring (SETTLE) takes over and carries it a pixel past and back. Let go slowly, the spring seats it on the nearest tick, every STEP units.

The click shows

Every frame the script looks at which hundreds the knob has crossed between where it was and where it is (as many as five in a frame during a fling), and each one clicks once only, until the knob moves 8 units away from it. The click stretches the tick by 6 units and lets it come back with elastic.out, lights it vermilion and fades it, and gives the index a little kick. The name of the weight is the nearest one, with 4 units of give past the halfway mark (so on 650 it does not flicker), it rolls the way the knob turns and is bright only when the knob sits right on the hundred.

The word, the guides and the preview

The word gets a font-weight with decimals every frame, and its size is chosen so that it fits even at 900, by measuring it at 900 and scaling it; the baseline is read from the bottom of an empty box sitting on the baseline, the x-height from measureText on the canvas. Everything is worked out again on resize. A click from a script (the library's preview) starts a whole round in a GSAP timeline: a slow turn past 500 and 600, a fling to Black, a long turn down to Light, and back to Regular.

Values to change

NameFileDefaultWhat it changes
WORDscript.js'Handgloves'The word set in the weight being chosen (18 letters at most).
STARTscript.js400The weight when the page opens, from 100 to 900.
STEPscript.js25How many units of weight between the ticks a knob let go comes to rest on.
SWEEPscript.js300How many degrees the knob turns from 100 to 900.
DETENTscript.js3000How hard every hundred holds the knob while it is turned past: at 0 no clicks.
FRICTIONscript.js4.5How soon a flung knob slows down: lower, and it goes further.
SETTLEscript.js[700, 0.55]The spring that seats the knob on its tick: how stiff and how held back (below 0.5 it overshoots more).

Try them in the Playground

When to use it

For the type panel of a design app, the site of a type foundry that lets you try its variable fonts, a configurator, the editor of a website or a newsletter, and in general for any value with fixed points along the way: change WORD, the names and the limits, and it becomes the knob of any axis.

On phones

Under 560 pixels the knob is 150 wide and the word shrinks by itself so that it fits even at 900 (about 50 pixels at 390). The finger turns it without scrolling the page (touch-action none on the knob), with the same clicks and the same fling; instead of the hover the touch has the press, which squeezes the face a little and lightens its edge.

With reduced motion

No springs and no flings: the knob follows the finger without clicks and let go goes straight to its tick, the keys and the wheel take it straight to the value, the name changes without rolling and the hundred's tick lights up and fades without stretching. The entrance is a fade, already at Regular.

Pitfalls

  • With a sine force over the whole scale (as in notched knobs) the knob could never rest between two hundreds: the wells are local, 16 units wide, and outside them the knob is free and rests every STEP.
  • The pretend hand (Home, End, the double click) took the knob as if it were the preview, and the live region stopped saying the weight: the pretend hand carries who asked for it, and only real gestures are announced.
  • During a fling the knob passes as many as five hundreds in one frame: the click is looked for between where it was and where it is, never just by checking whether it is close to a hundred.
  • Stopping on 650, exactly half-way between Semi Bold and Bold, the name flickered between the two with every half tenth of the spring: it needs 4 units of give past the halfway mark before it changes.
  • The word widens with the weight: its size is measured at 900, not at the weight of the moment, or at Black it runs off the edges of a phone.
  • The site's preview clicks the knob before the entrance has finished: the click is set aside and the round starts as soon as the entrance stops.

Libraries

GSAP 3.15.0, Fraunces (font variabile, coi pesi da 100 a 900 e la dimensione ottica) 5.3.0, Inter Tight (font variabile) 5.3.0.

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