Skip to content
animorio
IT
Back to the library

The ruler archive

Hover, TextGSAP, CSS onlyMediumCompressed weight: Demo 8.6 KBGSAP 28 KBFreeDownload the zip

A studio's archive, one project a year, on a thin ruler: under the pointer the ticks rise in a wave, each on a spring of its own, the orange needle snaps to the nearest year with the project's name hanging from it, and the big year rolls like an odometer, thin while it runs and heavy when it lands. Minimal style.

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 ruler archive</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>
  <main class="stage" data-stage>
    <header class="top">
      <span class="top__name">Studio Kesten</span>
      <span class="top__note">Archive, one project a year</span>
    </header>

    <!-- the year: four columns of digits that roll like an odometer, thin while they fly and heavy when they land -->
    <p class="year" aria-hidden="true" data-year></p>

    <!-- the ruler: one tall tick a year and thin ones between; under the pointer the ticks rise in a wave, each on its
         own spring, and the needle snaps from year to year carrying the name of the project -->
    <div class="ruler" role="slider" tabindex="0" aria-label="Archive year" data-ruler>
      <div class="ruler__ticks" data-ticks></div>
      <div class="needle" data-needle>
        <span class="needle__line" data-needle-line></span>
        <span class="caption" data-caption><span class="caption__mask" data-caption-mask></span></span>
      </div>
      <div class="ruler__labels" aria-hidden="true" data-labels></div>
    </div>

    <p class="hint">Move along the ruler</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.

18 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 ruler archive” from Animorio and fit it into my site

What it does

On warm white paper, at the top the studio's name, Studio Kesten, and on the right Archive, one project a year; in the middle a huge year, at the bottom a thin ruler from 1996 to 2026, with a tall tick for each year, taller every five and every ten, short ticks between and the labels 2000, 2010 and 2020 below. As the page opens the ticks grow from the left with a small bounce, the orange needle drops from above on a spring and runs once through the thirty years with the wave under it, while the year rolls fast up to 2026. Then, wherever the pointer goes on the page, the ticks under it rise in a soft wave, higher near the ruler and lower far from it; each tick chases it on a spring of its own, so a fast pointer leaves a ripple behind. The needle snaps to the nearest year on a spring that goes a hair past and comes back, the tick it lands on gets a small kick and the needle stretches and settles. Hanging from the top of the needle, the name of that year's project (Kiln & Co, Identity) slides out of its mask in the direction you are going, pushing the old one out like a belt, and over the last stretch of the ruler it moves to the left of the needle. The big year is an odometer driven by the same spring as the needle: each digit turns only while the one on its right goes from 9 to 0, and the digits turn very thin while they run and heavy again when they land. When nobody points, after a moment the needle wanders slowly by itself. The arrow keys move a year, Page Up and Page Down ten, Home and End go to the ends.

How it works

A ruler of ticks

The ruler is a row of i elements one pixel wide and a hundred tall, placed with left in percent: a tick for each year and STEPS spaces between two years. Each one has its resting height (taller every five and every ten years) and every frame it only gets transform: scaleY from its foot, so the lines stay crisp and nothing works the layout out again. It goes from grey to black with its opacity, by how far it has risen.

The wave on a spring for each tick

Each tick wants to rise by LIFT times a Gaussian bell, exp(−d²/2R²), with d the horizontal distance from the pointer and R equal to REACH (narrower on a short ruler). It does not take it at once: it chases it on a spring (TICK_SPRING) integrated by hand on GSAP's ticker with the step capped at 1/30 of a second. Behind a fast pointer the ticks sink a little under their size, never below a third.

The needle and the odometer

The year wanted is the one nearest to the pointer; the needle gets there on a spring of its own (NEEDLE_SPRING) and the same position, a number with decimals, moves the digits. Each column is a strip with the digits 0 to 9 and one more 0; the ones column stands at y mod 10, the others turn only while the column on their right goes from 9 to 10, like the wheels of a counter. The year's weight goes from WEIGHT[0] to WEIGHT[1] with the spring's speed.

The name hanging from the needle

At each new year the project's name comes into the mask from below when going on and from above when going back, and the old one leaves the other way on the same curve, so they never overlap; the kind of work follows a beat later. The change happens at most every tenth of a second. Over the last stretch of the ruler the caption slides to the left of the needle, and it never leaves the page.

Hands, keys and the pilot

The mouse drives the wave over the whole page, a finger only while it touches (the page has touch-action: pan-y, so it can still scroll up and down). The ruler is a role=slider with aria-valuetext: the arrows, Page Up and Down, Home and End bring the needle with a ghost pointer that glides. When the page opens a timeline grows the ticks and runs the needle; if nobody points, after 2.4 seconds the needle wanders on a slow sine.

Values to change

NameFileDefaultWhat it changes
REACHscript.js70How wide the wave of ticks is round the pointer, in pixels.
LIFTscript.js64How many pixels the tick right under the pointer rises.
TICK_SPRINGscript.js[300, 17]Each tick's spring: how stiff, and how much it is held back (less holds, more ripple).
NEEDLE_SPRINGscript.js[150, 16]The spring of the needle and of the rolling year: how stiff, and how much it is held back.
WEIGHTscript.js[720, 180]The weight of the year at rest, and while it rolls fast (100 to 900).
STEPSscript.js5The spaces between two years on the ruler (on a phone half as many).
WANDERscript.jstrueThe needle wanders by itself when nobody points.

Try them in the Playground

When to use it

For the archive or timeline of a studio, a photographer, a family business, a festival with many editions: one thing a year, to browse by passing over it. It works while the years are thirty or fifty or so; with many more the ticks get too dense and the wave takes in too many years at once.

On phones

The same animations with the sizes adapted: the ruler is as wide as the screen with half the ticks between two years, the wave is narrower, the year is a third of the width. The wave and the needle follow the finger while it touches and settle when it lifts; the page still scrolls up and down. The caption never leaves the screen.

With reduced motion

No wave, no springs and no rolling digits: the needle goes straight to the year, the new year appears with a short fade and the project's name swaps with a fade, without sliding. When the page opens everything fades in already in place, on 2026.

Pitfalls

  • The caption's texts were inline spans and the transform did not move them: the names all stayed still on top of each other. They need display: inline-block.
  • With the exit on power3.in the old name stood still while the new one arrived fast, and for a moment both could be read. Entry and exit on the same curve and the same duration run like a belt and never touch.
  • Sweeping fast over thirty years, a name change for each year put seven or eight in the mask at once: the change happens at most every tenth of a second, always with the latest year.
  • Lightly damped springs behind a fast pointer took the ticks below zero, and the ruler looked holed: the height never goes below a third of the resting one.
  • At weight 720 Inter Tight's zero is wider than 0.6 em and the column clipped its side: columns 0.7 em wide with a small negative margin.
  • The previews' pilot sends pointerleave events that bubble up from every element it leaves: the real exit is a pointerout with no relatedTarget and outside the window.
  • A mouse resting on the page must not start the wandering needle: the script remembers whether the mouse is inside, even when it moved during the opening, and at the end of the opening the needle goes where it stands.

Libraries

GSAP 3.15.0, Inter Tight (font variabile) 5.3.0.

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