Skip to content
animorio
IT
Back to the library

The instant photo gallery that develops on hover

Images, HoverGSAP, CanvasMediumCompressed weight: Demo 6.5 KBGSAP 28 KBFreeDownload the zip

A gallery of instant photos in the minimal style: on a warm white table three prints with white frames are still grey-blue and blank. Passing the pointer over one develops it slowly from the edges inwards, the blues first and the warm colours after, like a real instant photo; shaking the pointer over it hurries it. Once developed it stays, and a handwritten caption writes itself under the frame.

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>Pellen</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/figtree@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/caveat@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- three instant photos, still grey and blank: passing over one (or shaking the pointer over it) develops it
       from the edges inwards, the blues first and the warm colours later; once developed it stays, and a handwritten
       caption writes itself under the frame -->
  <main class="pagina" data-pagina>
    <header class="testa">
      <p class="marchio" data-entra>Pellen</p>
      <p class="testa__nota" data-entra>Instant prints</p>
    </header>

    <section class="fila" data-fila aria-label="Three instant photos">
      <figure class="istantanea" data-foto="mare">
        <div class="istantanea__ombra" data-ombra></div>
        <div class="istantanea__corpo">
          <canvas class="istantanea__tela" aria-label="The sea at low tide, at dusk" data-tela></canvas>
          <figcaption class="istantanea__scritta" data-scritta>low tide, 7pm</figcaption>
        </div>
      </figure>
      <figure class="istantanea" data-foto="sedia">
        <div class="istantanea__ombra" data-ombra></div>
        <div class="istantanea__corpo">
          <canvas class="istantanea__tela" aria-label="A chair in the sun against a wall" data-tela></canvas>
          <figcaption class="istantanea__scritta" data-scritta>the chair, noon</figcaption>
        </div>
      </figure>
      <figure class="istantanea" data-foto="vaso">
        <div class="istantanea__ombra" data-ombra></div>
        <div class="istantanea__corpo">
          <canvas class="istantanea__tela" aria-label="A clay vase with a branch on a table" data-tela></canvas>
          <figcaption class="istantanea__scritta" data-scritta>vase, may</figcaption>
        </div>
      </figure>
    </section>

    <footer class="piede">
      <p class="nota" data-entra data-nota>Hover to develop, shake to hurry it</p>
      <p class="stato" data-entra><span data-conta>0</span> of 3 developed</p>
    </footer>
  </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.

21 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 instant photo gallery that develops on hover” from Animorio and fit it into my site

What it does

Pellen is a made-up shop of instant prints. On a warm white table there are three square photos with white frames, a little crooked as if just put down: the sea at low tide at sunset, a chair in the sun against a wall, a clay vase with a branch. But nothing shows yet: they are grey-blue and blank, like an instant photo just out of the camera. Passing the pointer over one lifts it a few pixels, straightens it a little and starts developing it: the image comes up first at the edges and then in the centre, and the colours arrive in layers, the blues first, then the greens, and finally the warm reds and yellows, while the grain settles. Shaking the pointer over it, the way you shake a real instant photo, hurries it. When it is developed the print settles by a pixel, stays like that, and a handwritten caption writes itself under the frame in blue ink, the only colour on the page besides the photos. At the bottom a line says how many photos are developed; a few seconds after all three are ready, they go back to grey and it starts again. When nobody moves the pointer, a pretend pointer goes from one photo to the next and rubs them.

How it works

Three photos, drawn once

The photos are not loaded: each one is drawn once on a small 144 by 144 canvas, with gradients and simple shapes, and its pixels are kept. The real canvas on the page is bigger and gets the photo scaled up with high-quality smoothing, so it stays soft at any size.

Developing from the edges

Each photo has a number, p, from 0 to 1. For each pixel the local development is p·(1+EDGES) − EDGES·(1 − b), where b is how close the pixel is to the edge, with a small ripple: the edges come first, the centre last, and the front is not a perfect square.

Colours in layers

Three soft curves come from the local development: blue starts at once, green at half of WARMTH and red after WARMTH. Each channel goes from the grey-blue of the emulsion to the real colour on its own time, so the photo turns from cold to warm like a real instant photo; the grain, a fixed noise per pixel, settles as it goes.

Hover and shake

Every frame checks whether the pointer is over the photo or its frame: if so, p grows by dt/DEVELOP, multiplied by 1 + SHAKE times the pointer speed (up to three times). Coming in, the photo rises 5 pixels and straightens with elastic.out and its shadow widens; going out, it tilts back.

The caption and starting over

At p equal to 1 the print drops a pixel and comes back on a spring, and the Caveat caption writes itself from the left with a clip-path in a second and a half. With all three ready, after RESET seconds the captions are wiped and the photos go back to p = 0 one after the other.

Values to change

NameFileDefaultWhat it changes
DEVELOPscript.js2.6How many seconds of hovering a print takes to develop fully.
SHAKEscript.js1How much shaking the pointer hurries it: 0 switches it off.
EDGESscript.js0.55How far ahead of the centre the edges develop.
WARMTHscript.js0.24How much later than the blues the warm colours arrive.
GRAINscript.js0.05How grainy the emulsion is while it develops.
TILTscript.js2.4How tilted the prints lie on the table, in degrees.
RESETscript.js4.5After how many seconds the developed prints go grey again and it starts over.

Try them in the Playground

When to use it

In a photographer's or a print shop's gallery, in a studio portfolio, on the memories page of a hotel or an event: anywhere photos should arrive with a gesture rather than all at once.

On phones

The same animation: the photos are sized on both width and height and sit in a row in the box. A finger touching or rubbing a photo develops it; the line at the bottom says touch instead of hover.

With reduced motion

The photos are already developed and still, with their captions written: no movement, no pretend pointer, everything fades in.

Pitfalls

  • Redrawing every photo at its real size every frame is expensive: the development is computed on a small 144 by 144 canvas and only when p changes, then scaled up with drawImage.
  • The pointer speed has to be damped and left to fall on its own, otherwise one sharp move develops the photo all at once.
  • GSAP animates the whole figure while the frame and the sheen live on the child: that way GSAP's transform doesn't wipe the CSS one.

Libraries

GSAP 3.15.0, Figtree (font variabile) 5.3.0, Caveat (font variabile) 5.3.0.

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

Testing

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