Skip to content
animorio
IT
Back to the library

The photo sorted by light

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

In the minimal style: a photo of a lake at dusk cut into chips. A thin red line crosses it and every column it touches sorts its chips by light, bright ones up and dark ones down: the photo becomes a field of gradients, one per column, then the line passes again and every chip goes home.

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 sorted by light</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/instrument-sans@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <p class="mark" data-mark>Lowlight</p>

    <!-- the plate: the photo cut into small chips, column by column; a red hairline passes over it and every column
         it touches sorts its chips by light, then puts them back -->
    <figure class="plate" data-plate role="img">
      <canvas class="chips" data-chips aria-hidden="true"></canvas>
      <i class="head" data-head aria-hidden="true"></i>
      <figcaption class="cap" aria-hidden="true">
        <span class="cap__title" data-title></span>
        <span class="cap__state">
          <span class="cap__word" data-word="shot">As shot</span>
          <span class="cap__word" data-word="light">By light</span>
        </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.

16 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 sorted by light” from Animorio and fit it into my site

What it does

A paper-coloured page with the name of a made-up photo print studio, Lowlight, at the top left and a photo in the middle: a lake at dusk, the sky going from night blue to orange, the sun low behind the hills, its path on the water. Under it the caption Lake at dusk and on the right two words, As shot and By light: the one for the state the photo is in is bold, the other thin and grey. The photo is cut into chips, in twenty-eight columns. After a couple of seconds a one-pixel red line crosses the photo from left to right, and every column it touches sorts itself by light: the bright chips climb to the top, the dark ones sink to the bottom, starting one after the other from the top, each going one pixel past its place and coming back. As they run they lose their detail and become their average colour, and a thread of paper opens between them. When the line has passed the photo is a field of gradients, one per column, like a row of skies, and the bold has moved to By light with a small elastic. A moment later the line passes again and every chip goes back to its place in the photo, finding its detail as it lands; the bold goes back to As shot and it starts again. With the mouse over the still photo the columns under the pointer sort themselves just a little, on a spring, like a comb through the photo; a click sends the line across at once.

How it works

The photo in chips

The photo sits on a hidden canvas (drawn by the script or loaded from IMAGE). The script cuts it into COLUMNS columns and as many rows as it takes for the chips to be almost square, and with getImageData works out the average colour and the light of every chip (0.2126 R + 0.7152 G + 0.0722 B).

The order of each column

Every column sorts its chips by light, from the brightest to the darkest (LIGHT_ON_TOP), and a chip's place in that order is where it will go. Only the columns are sorted, not the whole photo: the chips only move up and down, and the sorted photo stays a field of vertical gradients that still recalls its sky.

A chip that runs and lands

Every column has a number, p, that a GSAP timeline takes from 0 to 1 when the red line passes over it. Inside the column every chip starts a little after the one above (SPREAD), runs to its place on a power3.out curve, then goes OVERSHOOT pixels past it and comes back on half a sine. In the first third of the run the detail fades into the average colour and the chip shrinks by GAP pixels, so a thread of paper stays between the chips.

All on one canvas

More than nine hundred chips are not elements of the page: GSAP's ticker redraws the canvas only when something has moved. A column at home is drawn in one piece, with no seams; the edges of the chips fall on whole pixels, so no thin lines are left between them.

The line and the two words

The red line is a one-pixel element that the timeline takes from left to right in SWEEP seconds; every column starts when the line reaches its centre. The two words under the photo keep their weight and width in two CSS variables read by font-variation-settings: the word of the new state takes its weight with elastic.out, the other turns thin and grey again.

Values to change

NameFileDefaultWhat it changes
IMAGEscript.js''The photo: an address, or a file loaded in the Playground. Empty, the script draws the photo. A photo from another site that cannot be read gives way to the drawn one.
CAPTIONscript.js'Lake at dusk'The caption under the photo.
COLUMNSscript.js28How many columns of chips the photo is cut into; the rows follow the photo's shape.
LIGHT_ON_TOPscript.jstrueThe bright chips climb to the top; with false they sink to the bottom and the sorted photo turns upside down.
SWEEPscript.js2.4The seconds the red line takes to cross the photo.
GAPscript.js1The pixels of paper between the chips once they are sorted (0 = none).
OVERSHOOTscript.js1How many pixels every chip goes past its place before coming back.
HOLDscript.js2.2How many seconds the photo stays still, whole or sorted, before the line passes again.
LOOPscript.jstrueWhether the photo sorts and comes back on and on. With false it does it once and then waits for a click.

Try them in the Playground

When to use it

To show a photo as something to look at twice: the opening of a photographer's or a colourist's portfolio, the page of a print for sale, the cover of a photo story, an app that works on photos. It works with any photo, including one loaded in the Playground.

On phones

The same animation with the sizes adapted: the photo is almost as wide as the screen and the columns are narrower. A tap on the photo sends the line across at once.

With reduced motion

Nothing moves: the photo fades in and stays. A click goes from the photo to the field of gradients (and back) with a fade, with no running chips.

Pitfalls

  • One page element per chip would mean more than nine hundred divs moving together, too many for a phone: it is all on one canvas, redrawn only when something moves.
  • Drawn in chips with edges that are not whole pixels, the still photo would show hairline seams between them (antialiasing): a column at home is drawn in one piece and the edges of the moving chips fall on whole pixels.
  • Under the pointer, half-sorted columns opened onto the paper, in holes: under the combed chips the whole column of the photo stays drawn.
  • A photo from another site without CORS permission cannot be read with getImageData: the script tries it with crossOrigin and, if it cannot read it, uses the drawn photo.

Libraries

GSAP 3.15.0, Instrument Sans (font variabile) 5.3.0.

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

Testing

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