Skip to content
animorio
IT
Back to the library

The photo on turning slats

Images, TransitionsGSAP, CanvasMediumCompressed weight: Demo 9.8 KBGSAP 28 KBFreeDownload the zip

In the minimal style: a photo cut into horizontal slats, like a blind. The slats turn over one after another from the top, each on a spring that goes a few degrees too far and settles, and the next photo is already waiting behind; the caption changes letter by letter, narrowing and widening on the width axis.

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 photo on turning slats</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>
  <main class="stage" data-stage>
    <p class="mark">Lattis</p>

    <!-- the plate: the script places it and cuts the photo into slats; behind them waits the next photo -->
    <figure class="plate" data-plate role="img">
      <div class="settle" data-settle>
        <div class="behind" data-behind aria-hidden="true"></div>
        <div class="slats" data-slats aria-hidden="true"></div>
      </div>
      <div class="ruler" data-ruler aria-hidden="true"></div>
      <i class="marker" data-marker aria-hidden="true"></i>
      <figcaption class="cap" aria-hidden="true">
        <span class="cap__title" data-title></span>
        <span class="cap__meta" data-meta></span>
      </figcaption>
    </figure>
  </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.

19 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 photo on turning slats” from Animorio and fit it into my site

What it does

A paper-coloured page, with the name of a made-up photography studio, Lattis, at the top left. In the middle there is a portrait photo and under it, on the left, a single word as its caption; on the right a small line with the shot's details. A thin ruler runs beside the left edge of the photo: a grey tick on every joint between two slats. At the start the ticks draw themselves from the top, and the slats arrive edge-on, invisible, and turn one after another until they show the first photo, a dune at dawn. A few seconds later the slats turn again, from the top down: each one rotates in 3D on its long axis, darkens as it turns its back on the light, goes a few degrees past its place and settles, and already carries the next photo on its back. Through the gaps between the turning slats you see the new photo waiting behind. A small red tick runs down the ruler with the wave, and every grey tick it meets lengthens for a moment and comes back with an elastic; when the last slat lands the whole photo sits down by one pixel. Meanwhile the caption changes letter by letter: the letters of the old word leave upwards, narrowing, and those of the new one come up from below, wide and light, then take their weight and settle on their width with a small elastic. There are three photos, drawn by the script on a canvas: the dune, low tide with a stone on the wet sand, an arch in a pink wall. Then it starts again from the first. With the mouse over the still photo, the slats near the pointer tilt and between them you can peek at the photo to come; a click on the photo turns the slats straight away.

How it works

One photo, many slats

The photo is cut into SLATS horizontal slats, each a div with two faces: on the front its strip of the current photo, on the back (turned by 180 degrees, with backface-visibility: hidden) the same strip of the next photo. Every face has the whole photo as its background, as big as the frame and moved up by the slat's distance from the top: so the still slats meet to the pixel. Under the slats there is a layer with the next photo, which shows through the gaps while they turn.

Every slat's spring

Every slat has an angle, a, and on every frame GSAP's ticker writes rotateX(a). To turn it goes from 0 to -180 degrees on a hand-made curve: the response of a damped spring, which starts still, goes OVERSHOOT degrees too far and settles. The damping comes from the overshoot you ask for, so the knob says exactly by how many degrees the slat misses before it settles.

The wave from the top

The slats start one after another, STAGGER seconds apart, from the first at the top. As they turn they darken: over every face there is a dark veil whose opacity grows the more the face turns its back on the viewer (1 minus the cosine of the angle). A red tick runs down the ruler in step with the wave, and when the last slat lands the whole photo drops by one pixel and comes back with an elastic.

The change without a jump

When the wave is over, every slat shows its back, that is the new photo. At that moment the fronts take the new photo, the backs and the layer underneath the one after that, and all the angles go back to zero: the picture stays identical and the next round starts from scratch. Every slat is one pixel taller than its share and sits under the next one, so between two still slats you never see a line of the photo behind.

The caption letter by letter

The caption is in Archivo, a variable typeface with the wght and wdth axes, and every letter is a span with two CSS variables read by font-variation-settings. The old word leaves upwards letter by letter while its width drops to 62; the new one comes up from below at width 125 and weight 220, and settles at 100 with elastic.out and at weight 560. The line's box cuts the letters above and below, so the two words never touch.

Values to change

NameFileDefaultWhat it changes
IMAGE_Ascript.js''The first photo: an address, or a file loaded in the Playground. Empty, the dune drawn by the script. The photo fills the portrait frame like background-size: cover.
IMAGE_Bscript.js''The second photo (empty: the low tide drawn by the script).
IMAGE_Cscript.js''The third photo (empty: the arch drawn by the script).
CAPTIONSscript.js[{ title: 'Dune', meta: 'f/8, 1/500 s' }, ...]The captions of the three photos, in order: the word that changes letter by letter and the small line on the right.
SLATSscript.js9How many slats the photo is cut into.
STAGGERscript.js0.07The seconds between one slat and the next (0 = they all turn together).
OVERSHOOTscript.js6By how many degrees a slat turns past its place before it settles (0 = it stops dead).
HOLDscript.js2.6How many seconds every photo stays still before the slats turn again.

Try them in the Playground

When to use it

To show a few photos calmly and with a recognisable gesture: the opening of a photographer's or an architect's portfolio, the rooms of a hotel or a holiday home, a restaurant's dishes, the covers of a travel blog. It works with any photo, including ones loaded in the Playground.

On phones

The same animation with the sizes adapted: the photo is almost as wide as the screen, the slats shorter, the ruler shorter and the caption smaller. A tap on the still photo turns the slats straight away.

With reduced motion

Nothing turns or slides: the photos and the captions take turns with a slow dissolve, the next photo appears from underneath while the first one fades.

Pitfalls

  • With the slats exactly as tall as their share, a thin line of the photo behind showed between two still slats (the edge of each slat is soft when the browser draws it on its own layer): every slat is one pixel taller and sits under the next one.
  • A slat edge-on, at 90 degrees, does not fully disappear with perspective: above the middle of the photo you see it from below and a thread remains. Close to 90 degrees the slat is hidden with visibility.
  • The turned faces use backface-visibility: hidden, which in Safari also needs the -webkit- prefix, like transform-style: preserve-3d on the slat: without it the back shows through the front.
  • A click during the pause stops the timeline before the change: the new caption was already waiting under the line and stayed there, invisible, confusing the next round. Now the waiting one is thrown away before another is made.
  • A photo loaded from another site cannot be redrawn on a canvas without locking it: the photos go in as the faces' CSS background, and only the ones made by the script go through the canvas.

Libraries

GSAP 3.15.0, Archivo (font variabile) 5.3.0.

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

Testing

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