Skip to content
animorio
IT
Back to the library

The paper lanterns

Hover, PhysicsGSAPAdvancedCompressed weight: Demo 12 KBGSAP 28 KBFreeDownload the zip

Strings of coloured paper lanterns cross a narrow street at dusk: brushing them with the pointer the lanterns swing like pendulums, knock their neighbours and the strings give. A click lights a lantern in another colour, with its bamboo ribs showing against the light, and a wave of lanterns lighting up runs along its string.

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>Paper lanterns</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/fraunces@5.3.0/full.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="stage" data-stage>
    <!-- the street at dusk, the strings across it and the paper lanterns: one SVG drawn by the script -->
    <svg class="street" data-street aria-hidden="true"></svg>

    <section class="copy" data-copy>
      <p class="copy__kicker" data-in>Hollow Lane, Friday nights in August</p>
      <h1 class="copy__title" data-in data-title>The Paper <em data-accent>Lantern</em> Fair</h1>
      <p class="copy__line" data-in>Four hundred lanterns over one narrow street, a food stall under every string and music until the last one goes out.</p>
      <p class="copy__when" data-in>From dusk to midnight. Free entry.</p>
    </section>

    <!-- one button for every lantern, for the keyboard: the pointer is handled by the stage -->
    <div class="keys" data-keys></div>

    <p class="hint" data-hint>Brush the lanterns. Click one to light its string.</p>
  </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.

35 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 paper lanterns” from Animorio and fit it into my site

What it does

The page of a made-up evening fair, The Paper Lantern Fair, on a narrow street, Hollow Lane, seen in perspective down its length: the house fronts with lit windows, the cobbles, the sky going from blue to sunset pink. Two strings run from wall to wall, a near one and a further, smaller one, with paper lanterns in six colours: round, tall or squat, with lacquered caps and a tassel. On arrival the strings are drawn from wall to wall, the lanterns drop on their cords with a bounce and a wave of light switches them on one after the other, on the near string from the left and on the far one from the right. Brushing them with the pointer the lanterns swing like pendulums, knock their neighbours and squash a little at every knock, the tassel flicks a moment late, and the string bends where the pointer crosses it and under the weight of the swinging lantern. The lantern under the pointer gets a little brighter. A click lights the lantern in a new colour: the light inside the paper rises, the bamboo ribs turn dark against it, the lantern jumps, and the wave runs along the string both ways, every lantern changing colour and lighting up with a small knock; in the title the word Lantern takes the new colour and springs with an elastic.

How it works

The street in perspective

Everything is one SVG drawn by the script at the size of the stage. There is a vanishing point in the middle: a point on a wall is found by saying how far down the street it is and how high on the wall, so windows, houses and cobbles get smaller on their own. Every string is fixed to the two walls at its distance, and on the far string everything is smaller.

The string is a rope of little weights

Every string is a row of points, fixed at the two walls and tied by pieces that cannot stretch (Verlet: at every step every point keeps its speed, then sixteen passes put the distances back). It is a little longer than the gap between the walls, so it sags (SAG). Before it is shown it is left to settle for five hundred steps, so it does not tremble on arrival.

The lanterns are pendulums

Every lantern hangs from its knot on the string: its angle and speed are kept. It feels gravity and also the acceleration of the knot, so a moving string makes it swing; in turn it pulls the knot along its cord with its weight and the pull of the swing, so the string bends. The physics runs at a fixed 120 steps a second.

The knocks

Two neighbouring lanterns on the same string are two circles: if they touch and are moving closer, they swap their speed along the line between them, with a bounce (BOUNCE), then they are pulled apart. At every knock the paper squashes and springs back, and the tassel flicks a moment late. The pointer gives its speed to the lanterns it passes through, checking the whole path of the frame, and drags the points of the string it crosses.

The light and the wave

The light is another shape like the paper, a little smaller, filled with a warm gradient: raising its opacity lights the lantern from inside, with nothing glowing outside. The ribs are dark lines over the paper, more visible the brighter it is. The click calls, for every lantern on the string, a lighting delayed by WAVE_GAP for every place of distance: new colour, light that rises and settles on SETTLE_GLOW, a little jump and a tap on the knot.

Values to change

NameFileDefaultWhat it changes
LANTERNSscript.js8How many lanterns on each string; fewer fit on a phone.
STRINGSscript.js2How many strings cross the street (1 to 3), from the nearest to the furthest.
SWINGscript.js1How hard the pointer pushes the lanterns.
DAMPINGscript.js1How fast they calm down: 0.3 keeps them swinging for a long time.
BOUNCEscript.js0.55How springy a knock between two lanterns is: 0 just leans them, 0.9 sends them flying.
SAGscript.js1How much the strings sag and how much they give under the pointer.
WAVE_GAPscript.js0.09How many seconds between one lantern lighting up and the next, in the wave.
SETTLE_GLOWscript.js0.72How bright a lantern stays after the wave (1 = full).

Try them in the Playground

When to use it

For the first page of a street party, an evening fair, a night market, a restaurant with an outdoor terrace, a music festival or a village feast: an object to touch that straight away brings the summer evening and the party.

On phones

The street is the same, with the vanishing point a little higher and fewer, bigger lanterns on each string. The lanterns move as you drag a finger through them; a tap lights the lantern and sends the wave. The physics, the knocks and the wave are the same.

With reduced motion

Nothing swings and the strings stay still: the lanterns are already hung and lit. The one under the pointer fades a little brighter; a click changes the colour and the light of the lanterns on the string one after the other, still fading, with no jumps.

Pitfalls

  • The lantern must feel the string and the string the lantern, otherwise they look like two drawings laid one over the other: the pendulum uses the acceleration of its knot, and the knot gets the weight and the pull of the lantern along the cord. The knot's acceleration, measured from one step to the next, is noisy: it must be smoothed and capped, or the lanterns tremble on their own.
  • A Verlet string just created is pulled straight and on the first frame it drops and bounces: let it settle before showing it, then reset its speed.
  • Two lanterns already touching that swap speed even while they move apart stick together: the swap only happens when they move closer, the separation always.
  • GSAP writes its own inline transform and wipes one written by hand: the SVG groups of the lanterns are moved only by the script, through the transform attribute, and GSAP only animates numbers in JavaScript objects (light, ribs, drop).
  • The preview video stops when nothing from GSAP is scheduled: a very faint breeze is a tween that always starts again, so the clock never stops.

Libraries

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

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

Testing

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