Skip to content
animorio
IT
Back to the library

The lift on scroll

Scroll, SVGGSAPAdvancedCompressed weight: Demo 21 KBGSAP + ScrollTrigger 45 KBLenis 5.3 KBFreeDownload the zip

Scroll inside the preview

A building cut in half like a doll’s house, with a glass lift in the middle: as you scroll the cabin rides up floor by floor, brakes, bounces on its cables, opens its doors and the floor switches on with its own little scene. The passenger bends the knees when it starts and rises on the toes when it brakes.

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 lift up the building</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/index.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/dm-mono@5.3.0/500.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- a made-up coworking building cut open like a doll's house. The stage sticks while you scroll: a glass lift rides
       up the middle floor by floor, brakes and bounces, opens its doors, and the floor it stops at switches on.
       The building, the rooms and the passenger are SVG drawn by the script -->
  <main>
    <section class="corsa" data-corsa>
      <div class="palco">
        <div class="finestra" data-finestra>
          <svg class="palazzo" data-palazzo aria-hidden="true"></svg>
        </div>

        <aside class="testo">
          <p class="testo__marchio">Halden Works &middot; Coworking</p>
          <div class="testo__testa">
            <div class="quadro" aria-hidden="true">
              <svg class="quadro__freccia" data-freccia viewBox="0 0 20 20"><path d="M10 2.5 17 11h-4.6v6.5H7.6V11H3z"/></svg>
              <span class="quadro__cifra" data-cifra><span>G</span></span>
            </div>
            <div class="testo__nomi">
              <p class="testo__piano" data-piano><span>Ground floor</span></p>
              <h2 class="testo__titolo" data-titolo><span>Halden Works</span></h2>
            </div>
          </div>
          <p class="testo__riga" data-riga><span>Six floors of desks, books and fresh air. Step in, the lift is waiting.</span></p>
          <nav class="pulsantiera" data-pulsantiera aria-label="Floors"></nav>
          <p class="testo__cenno" data-cenno>Scroll to ride up</p>
        </aside>
      </div>
    </section>

    <section class="uscita">
      <p class="uscita__marchio">Halden Works</p>
      <h2 class="uscita__titolo">Top floor. Mind the doors.</h2>
      <a class="tasto" href="#"><span>Book a desk</span></a>
    </section>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/ScrollTrigger.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/lenis@1.3.26/dist/lenis.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.

33 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 lift on scroll” from Animorio and fit it into my site

What it does

The stage stays still for the whole ride: on the left the cutaway of Halden Works, a made-up six-floor coworking building, on the right the floor’s name, a line of text and the lift panel. In the middle of the building is the shaft, with its rails, the counterweight and, up on the roof, the machine room with the cable wheel; inside the shaft a glass cabin with a passenger (a faceless figure with a shoulder bag). It starts in the lobby with the doors open: the sign drops in letter by letter, the revolving door turns, the bell on the desk rings. As you scroll the doors close and the cabin rises: the cables get shorter, the wheel turns, the counterweight drops, the floor slabs pass in front of the cabin, the clouds behind the windows move slower than the building and the camera follows a touch late. At every floor the cabin brakes, goes a little too far and settles with a bounce, and the passenger reacts: sinking at the knees when it starts, stretching when it brakes, arms opening and the bag jumping. Then the doors slide away, the floor’s light flickers on and the room comes alive: in the office the screens type, the chart draws itself, the sticky notes pop out and the printer prints; in the gym the mat unrolls, the bag swings, the treadmill runs and the timer counts; in the library the lamp comes on, the books hop in a row, the ladder slides along its rail, the page turns and the cat flicks its tail; in the hanging garden the plants grow with a spring, the irrigation drips, the hanging pots sway, two butterflies fly and the watering can tips; on the roof the parasol opens, the flag goes up and waves, the bunting drops and birds go by. The floor number changes in the cabin, on the plate by the door, on the big display and on the panel; the arrow lights up while the cabin travels and turns round when it goes down. The text changes with hopping letters. Pressing a button on the panel scrolls the page to that floor by itself. Scrolling back up, everything plays backwards and the floors left behind switch off.

How it works

A building in one SVG

The script draws everything in one SVG: the sky is the CSS background of the window, then a layer of clouds, then the world (ground, shaft, rooms, machine room, cabin, slabs). A floor is 340 units tall and every room is drawn in a box 380 wide, fixed to the shaft: on a phone the rooms are narrower and only the part near the lift shows, so the important things sit there. The back walls are a path with the window cut out (fill-rule evenodd), so the sky and the clouds show behind. The viewBox is as wide as the building and as tall as the window’s shape asks.

The ride in pieces

The scroll through the section becomes a position along the ride, split into pieces: stop (doors open), close, travel, open, stop, and so on up to the roof. From that number a function tells which floor the cabin is at (with power2.inOut on the journeys) and how open the doors are (back.out when opening, so they bang a little). The section is 100lvh tall plus as many lvh as there are pieces, so more floors means more scroll; SPEED shortens the journeys.

The bounce and the camera

The braking is a spring: when the cabin finishes a journey it gets a kick in the way it was going and a lightly damped spring brings it back to the floor, so it overshoots and comes back two or three times; when it leaves, a small kick the other way makes it dip for a moment. The camera (a translate on the world group) follows the cabin without the bounce and slightly late, so the bounce shows; the clouds move at a third of the speed. Cables, counterweight and wheel come from the same position: the counterweight drops as much as the cabin rises.

The passenger

The cabin’s speed is measured frame by frame and from it the acceleration, smoothed. The passenger is another spring pushed by that acceleration: when the cabin speeds up upwards the passenger lags behind and squashes (a vertical scale with the origin at the feet), when it brakes the passenger stretches. The arms open as hard as the push is and the bag jumps a bit more. SWAY sets how much the passenger reacts.

Floors that switch on

Every scene has two timelines: an entrance and a loop holding the endless repeats (screens, bag, ladder, drops, flag). When a floor’s doors are more than half open, the dark veil on the room goes off with a flicker, the entrance plays and the loop resumes with its timeScale rising from zero; when the cabin leaves the entrance plays backwards faster and the loop slows down to a stop. Numbers, text and panel follow the nearest floor; the title’s letters hop in word by word.

Values to change

NameFileDefaultWhat it changes
FLOORSscript.js5How many floors above the lobby, from 2 to 5: the top one is always the roof terrace, the others are office, gym, library and garden, in that order.
BOUNCEscript.js1How far the cabin overshoots the floor and bounces when it brakes (0 = it stops dead).
SPEEDscript.js1How fast the cabin rides: with 2 half the scroll takes it up a floor, with 0.5 it takes twice as much.
SWAYscript.js1How much the passenger sinks and stretches when the cabin starts and brakes (0 = still as a statue).
LIVELYscript.js1The speed of the floors’ little scenes once they are on: 2 is twice as fast, 0.5 half as fast.

Try them in the Playground

When to use it

To tell a building or a layered offer one floor at a time: the site of a coworking space, a hotel, a new office, a sports centre, an agency showing its departments, a product with several price tiers, an “about us” page split by team.

On phones

The same animation with the sizes adapted: the building sits on top and the text below, the rooms are narrower and show the part near the lift (the back windows only appear on a computer), the panel is smaller.

With reduced motion

No journey and no smooth scrolling: the building fades out and back in with the cabin already at the new floor, and the doors open with a fade. The rooms are already set up and light up with a fade, with nothing moving; the passenger stands still and the text changes with a fade.

Pitfalls

  • Braking made with the scroll ease alone stopped halfway if you stopped scrolling, and with fast scrolling you never saw it: the bounce is a time-based spring that starts when the cabin arrives and settles by itself whatever the scroll does.
  • The lowered flag at the foot of its pole, with the floor off, looked like a pink box resting behind the railing: when off it is also furled (a small scaleX) and unfurls as it goes up.
  • The title split into inline-block letters broke in the middle of words (“floo / r”): the letters sit inside one span per word with white-space: nowrap.
  • With fast scrolling the big number changed several times before its animation finished and stayed a floor behind: every change sends away all the old numbers, not only the first.
  • Scenes with endless repeats cost even when unseen: each floor’s loop is paused until its doors open and slows down to zero when the cabin leaves.
  • To rotate something already turned by its transform attribute (the leaves) GSAP rereads the matrix and loses the pivot: the fixed rotation sits on a group and GSAP animates the group inside, with svgOrigin.

Libraries

GSAP 3.15.0, Lenis 1.3.26, Bricolage Grotesque (font variabile) 5.3.0, DM Mono 5.3.0.

Compressed with gzip, the three demo files weigh 21 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 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