
The wheel that rounds off
Scroll, Physics
NewFree
Scroll inside the preview
The header of a made-up hotel, in the rich style: in a lobby with striped wallpaper, a checkered marble floor and a brass lift, as you scroll the guests’ bags fall one at a time onto the luggage cart with real physics, bounce, wedge in and pile up; the bell rings at every knock and the floor dial needle trembles. Scrolling back up empties the cart, and at the end the title and the button arrive.
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 suitcases on the hotel cart</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/wdth.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main>
<!-- the header of a made-up hotel, the Larkspur: a lobby with striped wallpaper, a marble floor, the lift with its
brass floor dial and a bellhop's brass luggage cart. Scrolling down, the guests' bags fall onto the cart one by
one with real physics (Matter.js) and pile up; scrolling back up lifts them away again. Tap a bag to bump it -->
<section class="carico" data-carico>
<div class="palco" data-palco>
<canvas class="scena" data-scena role="img" aria-label="A hotel lobby with a brass luggage cart. As you scroll, suitcases, a trunk, a hatbox and a duffel bag fall onto the cart and pile up."></canvas>
<header class="testata">
<p class="marchio"><svg viewBox="0 0 32 32" aria-hidden="true"><path d="M5 22h22M8 22a8 8 0 0 1 16 0M16 10v4M13 10h6"/></svg><span>Hotel Larkspur</span></p>
<p class="sotto">Since 1931, by the station</p>
</header>
<p class="targa" data-targa aria-live="polite"><span class="targa__su">Now loading</span><span class="targa__nome" data-targa-nome>The lobby</span></p>
<div class="finale" data-finale>
<h1 class="finale__titolo">We carry <em>the rest.</em></h1>
<p class="finale__testo">Leave your bags at the door. They’ll be in your room before you are.</p>
<a class="tasto" href="#" data-tasto><span>Book a room</span></a>
</div>
<p class="cenno" data-cenno><span>Scroll to load the cart</span><svg viewBox="0 0 12 16" aria-hidden="true"><path d="M6 1v13M1 9l5 5 5-5"/></svg></p>
</div>
</section>
<section class="dopo">
<p class="dopo__marchio">Hotel Larkspur</p>
<h2 class="dopo__titolo">Forty rooms, one brass cart.</h2>
<p class="dopo__testo">Our porters meet every train. Your luggage goes up the old lift, you go up the stairs.</p>
</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="https://cdn.jsdelivr.net/npm/matter-js@0.20.0/build/matter.min.js"></script>
<script src="script.js"></script>
</body>
</html>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
With the Animorio connector, Claude Code takes it from here, guide included, and fits it into your project. Paste this request:
Take “The hotel header with suitcases on the luggage cart” from Animorio and fit it into my siteScroll moves a number from 0 to 1 with scrub, and from it we know how many bags should be on the cart. Physics, though, runs in real time: if some are missing, a new one falls from above (at most one every 0.3 seconds); if there are too many, the last one becomes static and flies up. So scrub can never leave a bag halfway through its fall.
Matter.js has the platform, the two uprights, the floor and two side walls, all static: the bags are chamfered rectangles and the hatbox a circle, with high friction so the pile stays up. The engine steps at a fixed 1/60 of a second accumulated in the GSAP ticker, the same on every screen.
Everything is drawn in s units, the smaller of width over 640 and height over 780: the cart, the bags and the static bodies grow and shrink together, and the pile fits the phone box as it does the computer. On resize the static bodies are rebuilt and the bags fall again.
On collisionStart, if the impact speed passes a threshold, the bell gets a push and the floor needle a kick: both are damped springs computed every frame. The tags hanging from the bags are more springs tied to the body’s angular velocity.
Wallpaper, skirting, veined marble, lift and palm go on a spare canvas drawn only once (and again when the fonts arrive or the size changes); every frame copies it and draws the cart, the bags, the bell and the dial on top.
| Name | File | Default | What it changes |
|---|---|---|---|
HOTEL | script.js | 'Hotel Larkspur' | The hotel’s name on the cart’s plate. |
BAGS | script.js | 7 | How many bags fall onto the cart, from 3 to 7. |
GRAVITY | script.js | 1.1 | Gravity: higher, the bags fall and settle faster. |
BOUNCE | script.js | 0.18 | How much the bags bounce when they land. |
SCREENS | script.js | 5.6 | How long the loading lasts, in screens of scroll. |
BUMP | script.js | 1 | How high the top bag jumps at a tap or a click. |
For the header of a hotel, a bed and breakfast or a holiday home, a luggage storage or delivery service, a luggage shop, a travel agency or a packing app; and for any page where scrolling fills something up, a cart, an order, a list.
The same animation with the sizes adapted: the cart and the bags are measured on the smaller side of the box, so the whole pile fits on the phone too; the lift and the palm stay at the sides, partly off the edge. A tap bumps the top bag and finger scrolling stays free.
No falls, no bounces and no smooth scroll: the pile is computed silently on load and stays still, and as you scroll each bag fades in at its place; the bell and the needle stay put.
GSAP 3.15.0, Lenis 1.3.26, Matter.js 0.20.0, Fraunces (font variabile) 5.3.0, Mona Sans (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 13 KB; the libraries: GSAP + ScrollTrigger 45 KB, Lenis 5.3 KB, Matter.js 25 KB.
Tested on 23 October 2026
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.
With your account’s email and password.
or with your email
You’re signed in as .
With your account, you can download the zip of every animation and every pack, for free.