
The needle gauge
Counters, Physics, SVG
NewFree
On black, the new password of an account measured in time: how long a computer would need to guess it, on a logarithmic ruler from a second to ten thousand years. The needle sits on a spring and the ticks near it rise as it passes; past the dashed line of a century the ruler turns amber. The estimate is made here, reading the password in pieces (common passwords, words, years, runs, keyboard rows, repeats), and the weak pieces are bracketed under the password, drawn as a row of thin bars.
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 password on the time ruler</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/hubot-sans@5.3.0/wdth.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="stage">
<!-- a new password measured in time: how long a computer would take to guess it, on a ruler that runs from a
second to ten thousand years. The weak parts are bracketed under the password. Creating the account is
pretended: see post() in the script -->
<form class="pw" action="#" novalidate aria-labelledby="pw-title" data-pw data-autoclic>
<h2 class="pw__title" id="pw-title">Choose a password</h2>
<p class="pw__for">for your Margin account, mira@kiln.studio</p>
<input class="sr" type="email" name="username" autocomplete="username" value="mira@kiln.studio" readonly tabindex="-1" aria-hidden="true">
<label class="pw__label" for="pw-input">Password</label>
<div class="pw__box" data-box>
<div class="pw__slot" data-slot>
<input class="pw__input" id="pw-input" name="password" type="password" autocomplete="new-password" autocapitalize="off" autocorrect="off" spellcheck="false" enterkeyhint="done" maxlength="64" aria-describedby="pw-status" aria-invalid="false" data-input>
<span class="pw__cells" aria-hidden="true" data-cells></span>
<span class="pw__caret" aria-hidden="true" data-caret></span>
</div>
<button class="pw__show" type="button" aria-pressed="false" aria-controls="pw-input" data-show>Show</button>
</div>
<div class="pw__marks-clip"><div class="pw__marks" aria-hidden="true" data-marks></div></div>
<div class="ruler" aria-hidden="true" data-ruler>
<span class="ruler__tag" data-tag><span data-tag-text>a second</span></span>
<svg class="ruler__svg" data-svg>
<path class="ruler__ticks" data-ticks/>
<path class="ruler__base" data-base/>
<path class="ruler__fill" data-fill/>
<path class="ruler__goal" data-goal/>
<path class="ruler__needle" data-needle/>
</svg>
<div class="ruler__units" data-units></div>
</div>
<p class="pw__status" id="pw-status" data-status><span class="status__line">Measured in the time a computer would need to guess it.</span></p>
<button class="make" type="submit" data-make>
<span class="make__bg" aria-hidden="true"></span>
<span class="make__label" data-make-label>Create account</span>
</button>
<p class="sr" role="status" aria-live="polite" data-live></p>
</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.
22 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 password on the time ruler” from Animorio and fit it into my siteFrom every position the longest known piece is looked for: one of the nearly hundred most used passwords, a word (about 450, each with its rank times 20, as if among the words of a real dictionary), with the usual swaps (4 for a, 0 for o, @ for a) and capitals, a year between 1900 and 2099, a run like abcd or 4321, a keyboard row, a repeated character. Each piece is worth the guesses it takes to reach it; the characters left over are worth as many as the password’s possible characters, one by one. The product, divided by RATE guesses a second, is the seconds.
The ruler goes from a tenth of a second to ten thousand years in powers of ten: small ticks every quarter power, medium ones at every power, tall ones on second, minute, hour, day, month, year and GOAL years, marked by a dashed line. The ticks’ SVG path is rewritten at every frame: each rises BULGE pixels times a Gaussian of its distance from the needle, so the ticks make a dome that follows the needle.
The needle is a spring (STIFF, DAMP) integrated in small steps on the GSAP ticker, which sleeps when it is still: as you type the target changes at every key and the needle chases it without jumps. Pressing the button with a weak password it gets a push towards the century line and falls back. The words above follow it while staying inside the ruler, and change with a small vertical fade.
The field is an input type=password with autocomplete new-password and a hidden username for password managers; its dots are transparent and over it sits one cell per character, as wide as a character of JetBrains Mono (the field’s own type, so the caret falls right). In the cell there are a bar and the letter: Show switches to type=text and folds the bars into the letters one after the other. The new cells are found with the longest common subsequence, so typing in the middle only moves the ones after it.
| Name | File | Default | What it changes |
|---|---|---|---|
RATE | script.js | 10000 | The guesses a second of the attack measured: 10,000 is a stolen list of passwords stored with a slow hash. |
GOAL | script.js | 100 | The years a password has to hold out to be strong enough. |
SHORTEST | script.js | 8 | The fewest characters a password may have. |
STIFF | script.js | 240 | How stiff the needle’s spring is. |
DAMP | script.js | 20 | How much the needle’s spring is held back: lower, it swings further past. |
BULGE | script.js | 14 | How far the ticks near the needle rise, in pixels. |
WAIT | script.js | 0.8 | How many seconds the pretended account creation takes. |
In the sign-up or password change of an app, a service, a customer area: a time (in 2 minutes, in billions of years) is understood better than a red or green bar, and the brackets say why a password is weak. It also works in the security settings of an account.
The block takes the width of the screen; the ruler keeps second, hour, day, year and century (minute and month are hidden) and the ticks get closer. The field opens the keyboard without autocorrect and the Enter key says Done; Show is tapped as a 42-pixel button. A password longer than the field scrolls and the bars and brackets scroll with it.
The needle jumps straight to its place, with no spring and no opening sweep; the ticks stay raised where the needle is. The bars appear without growing, Show swaps bars and letters in one go, the brackets and messages fade in, and on sending there is no wave.
GSAP 3.15.0, Hubot Sans (font variabile) 5.3.0, JetBrains Mono (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 13 KB; the libraries: GSAP 28 KB.
Tested on 19 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.