Skip to content
animorio
IT
Back to the library

The word scale

Physics, TextGSAPAdvancedCompressed weight: Demo 11 KBGSAP 28 KBFreeDownload the zip

In the minimal style: a two-pan balance drawn in hairlines and six short words, each in a different weight of the same variable typeface. The blacker the word, the more it weighs. Clicked, it flies onto the lighter pan; dragged, it goes where you take it. The beam is a real damped pendulum: it leans, swings and settles, and when both sides weigh the same the needle stops on zero and lights up.

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>Weigh your words</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/roboto-flex@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- a two-pan balance drawn in hairlines: the words weigh what their type weighs, and the needle lights up on zero
       when the two sides are even. The lines are an SVG redrawn by the script at every frame. -->
  <main class="stage" data-stage>
    <svg class="lines" data-lines aria-hidden="true">
      <path class="guide" data-guide d="" />
      <path class="hair" data-base d="" />
      <path class="hair" data-post d="" />
      <path class="hair" data-ticks d="" />
      <path class="zero" data-zero d="" />
      <path class="needle" data-needle d="" />
      <path class="hair" data-strings-l d="" />
      <path class="hair" data-strings-r d="" />
      <path class="pan" data-pan-l d="" />
      <path class="pan" data-pan-r d="" />
      <path class="beam" data-beam d="" />
      <path class="knife" data-knife d="" />
    </svg>

    <span class="total" data-total-l aria-hidden="true">0</span>
    <span class="total" data-total-r aria-hidden="true">0</span>

    <div class="tray" data-tray></div>

    <p class="hint" data-hint>Click a word to weigh it, or drag it onto a pan.</p>
    <p class="read" aria-live="polite"><span class="read__label" data-read-label>Scale</span> <span class="read__clip"><b class="read__value" data-read>Empty</b></span></p>
  </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.

28 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 word scale” from Animorio and fit it into my site

What it does

On a warm white page the balance draws itself: first the base and the column from below, then the knife edge of the pivot, the beam growing from the middle to the tips, the needle rising and the ticks of the scale opening from zero to the sides, last the strings coming down and the two pans. The beam is born a little askew and, once everything is in place, it is let go: it swings and levels out. Underneath, six words rise one after the other, lead, stone, paper, silk, bread and salt, each in its own weight of the typeface, from 200 to 900, with the small number under it. The weight of the type is the weight of the word. Clicked, a word crouches, leaves narrowing on the width axis, makes an arc and comes straight down onto the lighter pan; it touches, squashes and springs back, the pan bends by a pixel, the words underneath feel the blow and the beam leans as far as the difference asks, with its swing and a small overshoot. The pans sway on their strings, each one a pendulum, and under each the total counts up to the new weight. The words stack tightly, one on top of the other; clicked again, a word goes back to its place and the ones above drop down a line. Dragged, a word goes wherever you take it and the pan it is about to fall into gets a thicker line. When both sides weigh the same and the beam comes to rest level, the needle lights up in vermilion, the zero tick grows longer and Even appears bottom right.

How it works

The weight is the type weight

Each word is a button with its own font-weight, from 100 to 900, and it weighs that number divided by a hundred. The typeface is Roboto Flex, with a weight axis from 100 to 1000 and a width axis from 25 to 151: the weight stays put because it is the word's identity, while the width moves (narrower in flight, wider in the squash). To stack them tightly, the true ink height of each word is measured on a canvas with measureText (actualBoundingBoxAscent and Descent), in the same weight: the line box would leave gaps.

The beam is a damped pendulum

The beam has an angle and a velocity, moved in fixed steps of a two-hundred-and-fortieth of a second inside gsap.ticker. The difference between the pans pushes with its lever (cos θ), the centre of mass of the beam, which sits under the pivot, brings it back level (sin θ), and damping at a fixed ratio does the rest: at rest tan θ is the difference over the sensitivity, so a hundred of difference is worth TILT degrees. The inertia grows with the load, so a full balance swings slower. Past STOP degrees the beam hits its stop and bounces back a little.

Pans hanging like pendulums

Each pan hangs from the tip of the beam with an angle of its own. From the position of the tip at every step come its velocity and acceleration, and the pan answers like a pendulum whose pivot moves: l ψ'' = ẍ cos ψ − (g − ÿ) sin ψ, plus a little damping. When the beam jerks or hits its stop, the pans lag behind and sway. The words on a pan turn with it, in its frame of reference.

The flight and the landing

The flight is a cubic curve that leaves upwards and comes straight down onto the pan from above, worked out again every frame because the pan moves. The weight only counts when the word touches, not when it leaves: on landing a small impulse in proportion to the weight and the falling speed pushes the beam, the pan bends with elastic.out and the word squashes with scaleY and the width axis; the ones underneath, the nearest first, do the same more softly.

When it stops on zero

If the two totals are equal and the beam is level and nearly still, a tween takes the needle from black to vermilion with back.out and lengthens the zero tick; any movement of the balance turns it off. When beam and pans are truly still the physics falls asleep and the beam goes to its exact angle, so the picture stays still. With reduced motion the balance fades in, the words fade out and back in where they go and the beam is already at the right angle.

Values to change

NameFileDefaultWhat it changes
WORDSscript.js['lead', 'stone', 'paper', 'silk', 'bread', 'salt']The words under the balance (up to eight, short ones).
WEIGHTSscript.js[900, 700, 300, 200, 500, 400]The type weight of each word, from 100 to 900: it is also what it weighs on the balance.
SWINGscript.js1.3The seconds of one swing of the empty beam; loaded, it swings slower, like a real one.
SETTLEscript.js0.6How soon the swing dies down: 0.2 swings for long, 1 settles with no overshoot.
TILTscript.js2.6How many degrees the beam leans for every 100 of difference between the two pans.
STOPscript.js15At how many degrees the beam hits its stop (and how far the needle's scale goes).
FLIGHTscript.js0.72The seconds a word takes to fly onto a pan.
KNOCKscript.js1How hard a landing word knocks its pan down (0 = it is laid down gently).
--accentstyle.css#e5391cThe colour of the needle when the two sides are even.

Try them in the Playground

When to use it

For a page that weighs two things against each other: two subscription plans, two offers, a before and after. For a type cover showing the weights of a typeface, a font's page, a portfolio that plays with words, a landing page that wants something to touch.

On phones

The same animations and the same physics, with the sizes adapted: the beam gets shorter so the pans stay on screen, the strings are shorter, the words smaller and on two lines. A tap sends a word to the lighter pan, a finger drags it.

With reduced motion

Nothing moves: the balance and the words fade in; a click fades the word out and back in on the pan (or in its place), and the beam is already at the right angle. When the sides are even the needle fades into colour.

Pitfalls

  • With a quadratic flight the word, leaving from below the pan, came into it from the side, through the rim and the strings: a cubic curve with its second control point above the pan brings it straight down from above.
  • With a low inertia of its own the loaded balance swung so much slower than the empty one that, after the last word, the needle reached zero more than four seconds later: the beam's own inertia is higher and the damping is a ratio, not a fixed number.
  • In the pendulum of the pans the vertical acceleration of the tip is taken away from gravity (g − ÿ), not added to it: with the wrong sign the pans began to sway exactly when the beam went down.
  • On the phone, with the beam 36 per cent of the screen long, the pans went off the sides: the length of the beam has another limit that takes the width of the pan into account.
  • If the weight counted at the click, the beam would lean before the word arrived: it counts on landing. The lighter pan, though, is picked counting the words in flight too, so two quick clicks do not end up on the same side.

Libraries

GSAP 3.15.0, Roboto Flex (font variabile) 5.3.0.

Compressed with gzip, the three demo files weigh 11 KB; the libraries: GSAP 28 KB.

Testing

Tested on 15 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 animations