Skip to content
animorio
IT
Back to the library

The shop's roller shutter

Transitions, SVGGSAP, CanvasAdvancedCompressed weight: Demo 15 KBGSAP 28 KBFreeDownload the zip

A click transition in front of a shop window: the painted roller shutter winds up over its roller slat after slat, with a catch halfway and a bounce at the top, and the lights come on inside. The next click pulls it down and the street slides on to the shop next door.

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 roller shutter</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/caveat@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/standard.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/mona-sans@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="street" data-street>
    <!-- the shops are built by the script, one at a time; the next one rolls in from the right -->
    <div class="shops" data-shops></div>

    <div class="pavement" data-pavement aria-hidden="true"><div class="pavement__tiles" data-tiles></div></div>

    <!-- for the keyboard (and the catalogue's autopilot): rolls the shutter up, or down and on to the next shop -->
    <div class="pull-spot">
      <button class="pull" type="button" data-pull data-autoclic aria-pressed="false">
        <span class="pull__bg" aria-hidden="true"></span>
        <span class="pull__text" data-pull-text>Open up</span>
      </button>
    </div>
  </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.

23 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 shop's roller shutter” from Animorio and fit it into my site

What it does

It is evening and the window of a made-up bakery, Marlow Bakery, is closed: above it is the sign, below it a shutter of metal slats with the shop's name hand-painted large on it, with a drop shade, paint runs, a brushed line of script and paint worn away here and there. At the top you see the roller, with the turns of shutter already wound on it and the hubs at the sides. On arrival the sign drops in and sways, the shutter settles with a bounce and the button pops out. On a click the key in the lock turns, the shutter jerks and starts to rise faster and faster: the slats, reaching the roller, turn over it one after another, getting shorter and darker, and the painting breaks up between the slats. Halfway the shutter catches, drops back a little and goes on with a jolt: the slats rattle, the housing shakes, the lamps inside swing and the first one flickers on. Then it runs up to the top, hits the stop and bounces. The other lamps come on one after another, the dark inside goes, the warm light spills out onto the pavement, an “Open” card drops into the window and swings, and the bread on the shelves gives a little hop. On the next click the lights go out, the card goes back up, the shutter gives a tug and comes down, hits the pavement with a bounce and a puff of dust and the lock closes again; then the street slides left and the next window comes in, a record shop (and after it a florist), closed, with its own painted shutter.

How it works

One measure

Everything is counted in slats. From the sign to the pavement there is room for the housing (0.8 slats), the upper half of the roller (ROLLER slats) and the whole shutter (SLATS slats): the height of one slat comes from that. The roller's centre is at height c and the shutter hangs from its front edge; the window starts one radius lower, so when it is open the part still hanging covers the roller.

The paint on the slats

The lettering is painted once on a canvas as big as the shutter: the picture, the name with its shade offset, the runs (where the row of pixels under the letters has paint, getImageData), the slanted brushed script and the worn paint, taken out with destination-out. It becomes an image and every slat uses it as its background, shifted down by one slat at a time: the shading of the grooves sits on top, so the lines run through the letters too.

The slats on the roller

A single number, p, says how far the shutter has risen. For every slat we know where its edges are along the shutter: below the roller a slat is flat; above, the edge is on the cylinder and, seen from the front, sits at R times the sine of the angle. The slat is placed with translateY and scaleY between its two edges, and a black layer darkens it by the sine of its middle angle: turning upwards it gets shorter and darker, one after the other. Past a quarter turn it disappears; the hubs turn by p over R.

The catch and the bounce

Opening is a timeline animating p: the jerk, the climb with power2.in up to halfway, then the catch (p drops back a third of a slat and goes on with elastic.out), the run to the top and the bounce against the stop with bounce.out. At every knock the faces of the slats (an element inside the one being moved) shake with a stagger from the bottom, the housing jumps and the lamps swing around their cord with svgOrigin.

The lights and the next window

The shop is an SVG with a dark veil over the goods and the lamps over the veil. Each lamp comes on with four steps of opacity without easing, and the veil and the light on the pavement change by one share per lamp. On closing everything goes back, the shutter falls with power2.in and bounces on the pavement with the dust; the next window is already waiting off screen and comes in with the pavement tiles, in the same timeline.

Values to change

NameFileDefaultWhat it changes
SLATSscript.js11How many slats make the shutter: more slats, thinner ones.
LIFTscript.js2.4The seconds the shutter takes to roll all the way up (a little less to come down).
CATCHscript.js1How hard the catch halfway is: 0 = it rises smoothly.
BOUNCEscript.js1How much it bounces at the top and on the pavement: 0 = it just stops.
ROLLERscript.js1.5The roller's radius, in slats: bigger, and the slats turn over it more slowly.
LAMP_GAPscript.js0.32The seconds between one lamp coming on and the next.
SPEEDscript.js1The speed of everything: 2 is twice as fast, 0.5 half as fast.

Try them in the Playground

When to use it

To move from a closed section to an open one with a gesture everybody knows: the page of a shop or a bar that opens, opening hours, a product launch, a new collection, moving between the windows of an online market or shopping street.

On phones

The same animation with the sizes adapted: the window is narrow and tall, the painted name goes onto two lines when it needs to (Fern & Fig), the hubs and the goods get smaller. A tap on the button or on the shutter opens and closes it.

With reduced motion

Nothing moves: the shutter fades away while the lights come on and the card appears; on closing the lights go out, the shutter fades back and the next window fades in.

Pitfalls

  • The slats have a z-index (the lower one covers the one above), and without a stacking context on the shutter they went in front of the hubs and the housing: the shutter has z-index 0.
  • With the roller hidden in its housing the slats' turn could not be seen: the housing only covers above the cylinder, and the front quarter turn stays in view.
  • The shake of the slats and their position are two different elements: the script writes the slat's transform on every frame, and GSAP on the same slat would wipe it out; GSAP moves the face inside.
  • The lock's golden face is a span: without display block its 100% width did not count and only the keyhole of the lock was left.
  • Adding the next window to a timeline already running, with a call at its end, could fire onComplete first: the new window is built straight away, off screen, and the timeline is born whole.
  • On the phone the hubs, as big as the roller, overlapped the shutter: their size is capped by the pilasters.

Libraries

GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0, Caveat (font variabile) 5.3.0, Fraunces (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.

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

Testing

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