
Blinds over images
Images, Scroll
NewFree
Scroll inside the preview
A minimal-style scroll animation for galleries: one print at a time opens in the middle inside a thin frame, a measuring line gives its height, then as you scroll it shrinks and travels down into its own slot in the index row at the bottom, where it lands a pixel too low and settles. When the row is full the title comes in.
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>Sable photo archive</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<!-- a made-up photo archive, Sable. The stage sticks while you scroll: one print at a time opens in a thin frame,
its size is measured on the side, then it shrinks along the page into its own slot in the index row at the
bottom, lands a pixel too low and settles. When the row is full the title comes in. The prints are drawn in
CSS, from the colours below -->
<main>
<section class="corsa" data-corsa>
<div class="palco" data-palco>
<header class="testa">
<a class="marchio" href="#">Sable</a>
<p class="testa__nota">Photo archive, 2019–2025</p>
</header>
<div class="quota" data-quota aria-hidden="true">
<span class="quota__riga" data-quota-riga></span>
<span class="quota__testo" data-quota-testo></span>
</div>
<p class="didascalia" data-didascalia aria-live="polite"><span data-did-titolo></span> <span class="didascalia__nota" data-did-nota></span></p>
<div class="stampe" data-stampe></div>
<ol class="indice" data-indice aria-label="Index"></ol>
<div class="finale" data-finale>
<h1 class="finale__titolo" data-finale-titolo>Five places, one light.</h1>
<span class="finale__riga" data-finale-riga></span>
<p class="finale__nota" data-finale-nota>The autumn index is complete.</p>
</div>
<p class="cenno" data-cenno><span>Scroll</span><svg viewBox="0 0 20 20" aria-hidden="true"><path d="M10 3v13M4.5 10.5 10 16l5.5-5.5"/></svg></p>
</div>
</section>
<footer class="piede">
<p>Sable keeps one print of every place it has stood in. Ask for the full index by letter.</p>
</footer>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.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.
31 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 prints that go into the index” from Animorio and fit it into my siteThe script measures the stage and works everything out in pixels from it: the slots of the row (at most a fifth of the row wide and at most 13% of the screen tall, in 4:5), the open print (in the free space between the header and the row, with the caption below and the dimension line on the right) and the spot for the final title. On resize it measures again, even halfway, and ScrollTrigger refreshes.
A ScrollTrigger without a timeline reads the section’s progress, Lenis smooths the scroll and an exponential average chases it once more (SMOOTH). The progress becomes a number u: each print has its own time t = u minus its place times 0.62, so the next one starts opening while the one before is leaving. From t come the opening (a clip-path from the bottom and a small zoom from 1.12 to 1, from 0 to 0.3), the dimension line (from 0.28) and the trip to the slot (from 0.55 to 0.95, with power3.inOut, a lerp of the position and a scale down to the slot’s size).
When a print crosses into its slot it gets a kick on a damped spring (LANDING and SPRING) that drops it a pixel or two and brings it back; the empty slot disappears under it and its name turns to ink. The vermilion mark under the row is a small GSAP tween, not tied to the scroll, which moves under the slot the open print is heading for.
In the last stretch the title comes in with opacity and eight pixels of rise, and its Archivo axes go from weight 260 and width 118 to weight 620 and width 94; the vermilion rule widens with scaleX and the note arrives last.
| Name | File | Default | What it changes |
|---|---|---|---|
PRINTS | script.js | ['Dune', 'Shore', 'Salt', 'Quarry', 'Night'] | The prints, in order (up to six). Short names: on a phone they sit under narrow slots. |
SIZES | script.js | ['24 x 30 cm', '30 x 40 cm', '20 x 25 cm', '40 x 50 cm', '24 x 30 cm'] | The size written beside each print; the dimension line shows the second number. |
OPEN | script.js | 0.62 | How big the open print is, as a share of the free space. |
SLOT | script.js | 0.13 | How tall a slot of the index can be, as a share of the screen height. |
LANDING | script.js | 30 | How hard a print lands in its slot: 0 sets it down without the extra pixel. |
SPRING | script.js | 300 | How stiff the landing spring is: more is quicker. |
SMOOTH | script.js | 6 | How quickly the prints catch up with the scroll: less is softer. |
RIDE | script.js | 1 | How much scroll the whole thing takes: 2 is twice as long. |
For the gallery of a photographer, an archive, an exhibition or a catalogue: a page that shows the images one at a time and puts them in order as you scroll, ending with a headline above the full row.
The same animation with the sizes adapted: the row of slots takes the whole width, the open print fits in the space left above it and the dimension line stays beside it. Everything is worked out again if the window changes size, even halfway.
Nothing moves and the scroll is not smoothed: the five prints are already in the row, with the title, the rule and the note above, and the page fades in.
GSAP 3.15.0, ScrollTrigger 3.15.0, Lenis 1.3.26, Archivo (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 7.3 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB.
Tested on 22 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.