Skip to content
animorio
IT
Back to the library

Words in the balance

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

In the minimal style: two words at the ends of a thin beam balanced on a fulcrum, and the weight of the type is the real weight, measured on the ink of the letters. A click gives the weight to one word: it turns black and bold, the beam leans its way on a spring and the word left light, up high, slips a little towards the middle.

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>This or that</title>
  <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>
  <!-- two words on a thin beam balanced on a fulcrum: the weight of the type is the weight on the scale -->
  <main class="stage" data-stage>
    <div class="balance" data-balance>
      <svg class="lines" data-lines aria-hidden="true">
        <path class="fulcrum" data-fulcrum d="" />
        <path class="plinth" data-plinth d="" />
        <path class="dial" data-dial d="" />
        <path class="ticks" data-ticks d="" />
        <path class="beam" data-beam d="" />
        <path class="stop" data-stop-l d="" />
        <path class="stop" data-stop-r d="" />
        <path class="needle" data-needle d="" />
        <circle class="pin" data-pin cx="0" cy="0" r="2.6" />
      </svg>
      <button class="word" type="button" data-word="left" data-autoclic aria-label="Give the weight to this">
        <span class="word__box" data-box><span class="word__ink" data-ink>this</span></span>
        <span class="word__cap" data-cap>wght <b data-num>530</b></span>
      </button>
      <button class="word" type="button" data-word="right" data-autoclic aria-label="Give the weight to that">
        <span class="word__box" data-box><span class="word__ink" data-ink>that</span></span>
        <span class="word__cap" data-cap>wght <b data-num>530</b></span>
      </button>
    </div>
    <p class="hint" data-hint>Click a word to give it the weight.</p>
    <p class="read" data-readout><span class="read__label">Tilt</span> <b class="read__value" data-read>0.0°</b></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.

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 “Words in the balance” from Animorio and fit it into my site

What it does

A warm white page and, in the middle, a balance drawn in thin lines. First the base draws itself, then the fulcrum, a slender triangle; on its tip the beam grows from the middle to both ends, the two stops appear at its ends, ticks under the beam like on a ruler and, over the pivot, a small dial with a vermilion needle. From above this drops onto the left end: the beam takes the blow and tips, the letters squash one after the other. Then that drops onto the right end and the beam, after a few swings, comes back level. Under each word a small dimension gives its weight, wght 530. Clicking a word gives it the weight: in a moment it turns bold (wght 860, with a little jump past it and back), squats like someone taking a load on their shoulders and the letters feel the blow one after the other; the other one lightens to wght 200, turns thin and almost breathes out. The mass of each word is the ink of its letters at that weight, so the beam really leans: it goes past, comes back and settles on a spring, the needle marks the degrees on the dial and the tilt can be read bottom right. In the strongest swing the light word, up high, loses its grip and slips a little towards the middle over the ticks; when it is the one with the weight, the beam goes its way and it runs back down to its stop, which gives a little under the knock. Clicking the word that has the weight again makes the two words equal. With the mouse over a word, the word gets a touch bolder and the beam leans a hair its way, like a finger on the pan.

How it works

Mass is ink

At start each word is drawn on a hidden canvas at the nine weights of the variable font (100 to 900) and the filled pixels are counted: that is its mass at that weight. Between weights the mass is interpolated, so as the word grows bold the scale feels the weight rise frame by frame. A tare makes the two words weigh the same at the same weight, even when one has more letters or wider ones: the empty scale starts level.

A balance with its spring

The beam is a body turning on the pivot, moved in fixed steps of a two-hundred-and-fortieth of a second inside gsap.ticker. The two words give it a torque (mass times distance from the pivot) and a restoring spring brings it back towards level, like the low weight of a real balance: so the tilt follows the difference in weight instead of always ending on the ground. The stiffness comes from TILT (how many degrees with a heavy word against a light one), the speed from SWING and the damping from DAMPING; with little damping the beam overshoots and comes back, and that is where the physics shows.

The words' grip

Each word has its place on the beam and its speed. Standing still, it stays put until the slope under it (the beam's angle plus the bend of the arm) beats the friction angle, GRIP times the normal tilt: that only happens in the strongest moment of a swing. Once moving it holds a little less, and it slides until the swing comes back under. The two words share the same beam and feel the same swing: what the light one loses slipping towards the middle it gets back when it is the heavy one and runs down to its stop.

A beam that bends, and the stops

The beam is not a straight line: each arm bends a little under its word, like a shelf loaded at its tip (the curve of a cantilever), and the bend has its own quick spring, so it quivers when a word lands. The beam is drawn as a polyline of thirty points, and each word stands on the right point at the local angle. When a sliding word knocks into its stop, the stop bends and comes back with elastic.out and the letters squash on the side of the knock.

The weight of the type as a gesture

The click runs a GSAP tween on the word's weight, with elastic.out: the type goes through a slightly heavier weight and back, while scaleX and scaleY give the squash and the letters dip and rise staggered. The weight reaches the page as font-weight, only when it changes by a unit. With reduced motion nothing moves: the balance fades out, the weights and the tilt take their places and the balance fades back in.

Values to change

NameFileDefaultWhat it changes
LEFT_WORDscript.js'this'The word on the left end of the beam (up to 14 letters: long words get smaller to fit).
RIGHT_WORDscript.js'that'The word on the right end of the beam.
LIGHTscript.js200The weight of the type of the light word, from 100 to 900.
HEAVYscript.js860The weight of the type of the word that has the weight: the further from LIGHT, the sharper the difference between the two words.
TILTscript.js5How many degrees the beam leans when a heavy word faces a light one.
SWINGscript.js0.9How fast the beam swings, in swings per second: 0.4 is a big slow scale, 2 a nervous little one.
DAMPINGscript.js0.22How soon the swing dies down: 0.1 rocks for a long time (and the words slip more), 0.4 settles almost at once and the words do not slip.
GRIPscript.js1.25How well the words hold: the slope that makes them slip, in times the normal tilt. Lower and they slip more, higher and they stay put.

Try them in the Playground

When to use it

To set two things against each other with a gesture: a heading that asks you to choose (this or that, before or after, monthly or yearly), the opening of a type designer's portfolio, the page that presents a variable font, a playful moment in a landing page.

On phones

The same balance with the sizes adapted: the arms take almost the whole width, the words are bigger relative to the arms and the physics is the same, in proportion. A tap on a word gives it the weight; there is no hover lean, since a phone has no hover.

With reduced motion

Nothing moves: the balance fades in already level with the words in place. A click fades it out and back in with the new weights and the beam already tilted where it comes to rest.

Pitfalls

  • With a beam simply resting on a fulcrum, any difference in weight always sends it to the ground: a tilt that follows the weights needs a restoring spring, like the weight under the pivot of a real balance.
  • With sliding friction much lower than standing friction, the light word never stopped: slipping towards the middle it took weight off its side, the beam leaned further and it slipped again, all the way. Sliding friction is just below standing friction, so the word stops as soon as the swing comes back under.
  • With the extra push from the beam's acceleration (a word on an end flicked up and stopped presses less) the light word slid a lot and the heavy one never got back to its stop: after a few clicks both were in the middle. What is left is the slope and the outward pull of the swing, the same for both.
  • Two different words at the same weight do not have the same ink (that has more than this), and the empty scale started half a degree askew: a tare evens the two words out at the middle weight.
  • The words started half a page above the beam, and in the first frames they showed cut off at the top of the screen: now they start outside the page, above its edge, and stay upright until they touch the beam.
  • The card's video stops when the picture stays the same for a second with no GSAP animation scheduled: while the physics is awake a gsap.delayedCall is always pending, and it only falls asleep when the beam is still at its balance.

Libraries

GSAP 3.15.0, Inter Tight (font variabile) 5.3.0.

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

Testing

Tested on 14 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