Skip to content
animorio
IT
Back to the library

The lens on the strip

A strip of stamps glides under a round lens: outside it is blurred and dim, inside the lens it is sharp, bright and larger. It slows down under the mouse, and it can be dragged and thrown.

Hover, ImagesGSAP, CSS onlyMediumLifetime

The code

A folder that runs on its own: index.html, style.css, script.js and the libraries from a CDN.

The code for this animation is part of lifetime access.

The preview stays open: watch it, slow it down, try it on your phone.

Lifetime access

What it does

On a dark green album page, a glassine strip carries a row of drawn stamps: a lighthouse, a sunflower, a comet, a whale and eight more. The row glides left by itself, blurred and almost colourless. In the middle sits a round lens with a brass rim: whatever passes under it is sharp, bright and a little larger, and under the lens you read the name and value of the current stamp, which changes with a small jump. With the mouse over it the strip slows almost to a stop; dragging moves it, and letting go with a quick gesture it glides on and then resumes its pace. With focus and the arrow keys you move one stamp at a time.

How it works

Two identical strips

The strip exists twice, with the same stamps in the same order: one behind, full width, with filter: blur(3px) brightness(0.5) saturate(0.55); one inside the lens, a circle made with clip-path: circle(50%), sharp. The same number moves both, so they cannot fall out of step.

Enlarging around a point

A point of the strip that sits at x behind must sit at c + s × (x − c) inside the lens, where c is the lens centre and s the magnification, 1.18. With transform-origin at the top left one transform is enough: translate(r + s × (x − c), r + s × (top − cy)) scale(s), where r is the lens radius.

An endless loop

One loop is the whole set: twelve stamps times their pitch. The strip holds as many copies as it takes to cover the screen, plus one, and the drawn position is x − ⌈x / loop⌉ × loop, always between minus one loop and zero: the number grows without limit, the strip does not.

Slowing, dragging, throwing

Every frame the speed chases its target with 1 − e^(−2.4 × dt): 46 pixels a second, 9 with the mouse over it. Dragging measures the speed of the gesture’s last tenth of a second; letting go, the strip starts from it and returns to its pace by itself, with no hand-written curve. The stamp under the lens is round((c − x − half a stamp) / pitch), modulo twelve.

Values to change

NameFileDefaultWhat it changes
FRANCOBOLLIscript.js12 francobolliName, value and drawing of each stamp: the drawing is a piece of SVG in an 84 × 94 frame, inside a 100 × 125 sheet that is already perforated.
PASSO, LENTOscript.js46, 9Pixels per second of the strip, on its own and with the mouse over it.
INGRANDISCEscript.js1.18How much the lens enlarges: with the lens one and a half times as wide as the stamp, a whole stamp fits inside up to about 1.2.
--fbstyle.cssclamp(128px, 24vh, 232px)The height of a stamp: strip, lens and caption follow from it.

When to use it

For a collection to browse without hurry: products, covers, labels, works. The lens says where to look and the strip hints that there are more.

On phones

Smaller stamps and lens; a sideways finger drags and throws the strip, a vertical one scrolls the page.

With reduced motion

The strip stands still, with the first stamp under the lens: it only moves by dragging or with the arrow keys, without inertia and without the name’s jump.

Pitfalls

  • The blurred strip must be separate from the lens: with backdrop-filter the blur is redone every frame over the whole band, with filter on the moving strip the browser keeps it in its layer.
  • Inside the lens you need a solid background: between one stamp and the next you would see the blurred strip behind.
  • Do not reset the number at every loop: letting it grow and wrapping only what is drawn avoids jumps during a GSAP tween on the arrow keys.
  • Measure the throw speed on the events’ own times (event.timeStamp), as the movement of the last tenth of a second divided by its time: dividing event by event, two events in the same frame look instantaneous and the throw explodes. A finger held still for more than a tenth of a second does not throw.

Libraries

GSAP 3.15.0, Mona Sans (font variabile) 5.3.0.

Weight: 21 KB of our own files.

Testing

Tested on 27 September 2026

  • Desktop: Done
  • Phone: Done
  • Reduced motion: Done
  • Safari on iPhone: Done

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