Skip to content
animorio
IT
All components

The delivery street

Pickers, SVG, Physics, TransitionsGSAPAdvancedCompressed weight: Demo 17 KBGSAP 28 KBFreeDownload the zip

The delivery choice in a plant shop's basket, as three cards: the chosen one opens a window onto a long street drawn in SVG. Choosing another, the window closes in the old card and opens in the new one while the camera travels along the street, its layers sliding past at their own speeds: from the country road of the van to the town of the cargo bike, all the way to the shop. The van or the bike rolls in and brakes, and the body, the rider and the plant in the box rock on springs; at the shop the awning slides out of its box and the clock turns to four. The sign of the choice is a parcel that drops into its slot.

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 delivery street</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/gabarito@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the delivery choice at the checkout of a plant shop: three real radio buttons, each a card. The chosen card
         opens a window onto one long street, drawn in SVG: the country road where the van drives, the town where
         the courier rides a cargo bike, and the shop itself. Choosing another card, the window closes in the old one
         and opens in the new one while the camera travels along the street, its layers sliding past each other; the
         van or the bike rolls in and brakes on its springs, and at the shop the awning unrolls and the clock turns
         to four. The sign of the choice is a parcel that drops into its slot. Under the cards, when it arrives -->
    <form class="ship" data-delivery onsubmit="return false">
      <fieldset class="ship__set" data-set data-autoclic>
        <legend class="ship__title">Delivery</legend>

        <label class="opt" data-opt data-days="5" data-working="true" data-say="Arrives by {date}">
          <input class="opt__input" type="radio" name="delivery" value="standard">
          <span class="opt__bay" aria-hidden="true" data-bay><span class="opt__win" data-win></span></span>
          <span class="opt__row">
            <svg class="opt__sign" viewBox="0 0 28 28" aria-hidden="true" data-sign>
              <rect class="sign__slot" x="4.5" y="4.5" width="19" height="19" rx="5"/>
              <g class="sign__box" data-box>
                <rect class="sign__kraft" x="4" y="4" width="20" height="20" rx="4"/>
                <rect class="sign__tape" x="11.5" y="4" width="5" height="20" data-tape/>
                <rect class="sign__label" x="16.5" y="16" width="5" height="4" rx="1"/>
              </g>
            </svg>
            <span class="opt__text">
              <span class="opt__name">Standard</span>
              <span class="opt__when">3–5 working days</span>
            </span>
            <span class="opt__price is-free">Free</span>
          </span>
        </label>

        <label class="opt" data-opt data-days="1" data-working="false" data-say="Arrives {date}">
          <input class="opt__input" type="radio" name="delivery" value="express">
          <span class="opt__bay" aria-hidden="true" data-bay><span class="opt__win" data-win></span></span>
          <span class="opt__row">
            <svg class="opt__sign" viewBox="0 0 28 28" aria-hidden="true" data-sign>
              <rect class="sign__slot" x="4.5" y="4.5" width="19" height="19" rx="5"/>
              <g class="sign__box" data-box>
                <rect class="sign__kraft" x="4" y="4" width="20" height="20" rx="4"/>
                <rect class="sign__tape" x="11.5" y="4" width="5" height="20" data-tape/>
                <rect class="sign__label" x="16.5" y="16" width="5" height="4" rx="1"/>
              </g>
            </svg>
            <span class="opt__text">
              <span class="opt__name">Express</span>
              <span class="opt__when">Tomorrow by 1 pm</span>
            </span>
            <span class="opt__price">€6.90</span>
          </span>
        </label>

        <label class="opt" data-opt data-days="0" data-working="false" data-say="Ready today, {date}">
          <input class="opt__input" type="radio" name="delivery" value="pickup">
          <span class="opt__bay" aria-hidden="true" data-bay><span class="opt__win" data-win></span></span>
          <span class="opt__row">
            <svg class="opt__sign" viewBox="0 0 28 28" aria-hidden="true" data-sign>
              <rect class="sign__slot" x="4.5" y="4.5" width="19" height="19" rx="5"/>
              <g class="sign__box" data-box>
                <rect class="sign__kraft" x="4" y="4" width="20" height="20" rx="4"/>
                <rect class="sign__tape" x="11.5" y="4" width="5" height="20" data-tape/>
                <rect class="sign__label" x="16.5" y="16" width="5" height="4" rx="1"/>
              </g>
            </svg>
            <span class="opt__text">
              <span class="opt__name">Pick up at the shop</span>
              <span class="opt__when">Today after 4 pm</span>
            </span>
            <span class="opt__price is-free">Free</span>
          </span>
        </label>
      </fieldset>

      <p class="ship__sum" aria-hidden="true" data-sum></p>
      <p class="sr" aria-live="polite" data-live></p>
    </form>

    <!-- the gradients of the street, shared by its three windows -->
    <svg class="defs" aria-hidden="true" focusable="false">
      <defs>
        <linearGradient id="street-sky" x1="0" y1="0" x2="0" y2="1">
          <stop class="w-sky-top" offset="0"/>
          <stop class="w-sky-low" offset="0.72"/>
        </linearGradient>
        <linearGradient id="street-glass" x1="0" y1="0" x2="1" y2="1">
          <stop offset="0" stop-color="#ffffff" stop-opacity="0.55"/>
          <stop offset="0.45" stop-color="#ffffff" stop-opacity="0"/>
        </linearGradient>
      </defs>
    </svg>
  </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.

36 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 delivery street” from Animorio and fit it into my site

What it does

On a white background, alone, the Delivery block of the basket of Fernhouse, a made-up plant shop, 400 pixels wide: under the title three white cards with round corners, Standard (3–5 working days, Free), Express (Tomorrow by 1 pm, €6.90) and Pick up at the shop (Today after 4 pm, Free), and under the cards a line that says when it arrives, such as Arrives by Wednesday 14 October, with the date in black. On the left of every card there is a dashed slot; the chosen one holds a cardboard parcel with its tape and label, the card has a dark edge and at its top a window 120 pixels tall opens onto a drawn street: for Standard the shop's green van on a country road, with fields, a fence, poplars and a distant warehouse; for Express the courier in a yellow jacket on a cargo bike with a plant in the box, in a street of pastel houses; for the pickup the green shop with its sign, the striped awning, the window full of plants, the Open sign on the door and a clock standing at four. It is one street, and every window looks at it through one camera. Choosing another card, the parcel lifts out of the old slot and fades, and a new one drops into the new slot turning, squashes as it lands and the tape runs over it. Meanwhile the window closes in the old card and opens in the new one, always attached to the card's words, while the camera travels along the street: the clouds barely move, the hills a little, the houses more, the road all the way and the bushes in front rush past. The van or the bike comes along, brakes to a stop right at its place and rocks: the van's body tips forward, the rider leans and the plant in the box bends, then they swing back and settle; the wheels turn with the road covered and the rider pedals. At the shop the awning slides out of its box, its scalloped edge flaps a little, the sign on the door swings and the hands turn to four. Below, the words of the line that change roll out at the top and the new ones rise from below, while the others close up or open up to make room. With the mouse over a card its edge darkens and the slot takes the shadow of the parcel.

How it works

Three real radios

The block is a fieldset with the legend Delivery, and every card is a label holding its radio input, hidden but present: it takes the focus, the arrows change the choice by themselves as in any radio group (from one end round to the other too) and screen readers read the name, the time and the price, while the street and the parcel are aria-hidden. The line saying when is announced by a hidden aria-live polite paragraph, written once per choice. The focus ring goes round the card only with the keyboard.

One street in three windows

The street is an SVG written by the script, more than a thousand units wide and 120 tall, with the three scenes 420 units apart. Every window has a copy of it, seen by the same camera, with six layers at their own depth: clouds 0.06, far hills 0.16, hills 0.32, houses 0.55, the road 1 and the bushes in front 1.5; every layer is moved by half the window minus the camera times its depth. The gradients live in one hidden SVG, and the awning's clip has a different id in every copy.

The window that moves

Every card has an opening value, from 0 to 1, which goes towards 1 for the chosen card and towards 0 for the others with a power2.inOut tween OPEN seconds long. The holder is opening times (SCENE + 6) pixels tall, the window opening times SCENE, anchored at the bottom: the street stays attached to the card's words and the window opens from its top edge. A window a few pixels tall would be a dark stripe of tarmac, so it fades at both ends. During a change the three cards add up to the same height, and when interrupted every window carries on from where it is.

The camera and the vehicles

The camera is a critically damped spring (frequency PAN) with a top speed of 1500 units a second, worked out on the GSAP ticker in steps of 1/240 of a second with the frame capped at 1/30. The new scene's van or bike starts out of sight and already moving: it goes at a steady speed while the camera travels, then brakes with a constant deceleration (power1.out over 0.75 seconds) and stops all at once. While it brakes a constant force acts on three lightly damped springs, the tilt of the body, the rider's lean and the plant's bend; when the braking ends at once the springs swing back and settle in little more than a second.

The rider, worked out on every frame

The wheels turn by the road covered divided by the radius, the crank by half the back wheel. The two legs are two bones of 17.5 units from the hip to the pedal, with the knee found by the law of cosines and bent forwards; the arm goes from the shoulder to the handlebar the same way, and the torso and the head turn round the hip with the spring's lean. The paths are written again only when they change.

The shop and when

The shop waits until the camera is near: then the awning slides out of its box (everything above the box's bottom edge is cut by a clipPath), the scalloped edge is redrawn on every frame with a wave that dies away, the sign on the door is a pendulum given a push and the hands go from a quarter past one to four. The line saying when takes the date from today, counting working days for Standard; every word has a key (before the date, the date, after it) and only the words that differ change, each in its own slot that takes the new width. When everything is still the loop leaves the ticker and draws nothing more; the library's preview clicks the group, which has data-autoclic, and moves to the next card.

Values to change

NameFileDefaultWhat it changes
STARTscript.js0The card chosen when the page opens (0 is the first).
SCENEscript.js120The height of the street in the chosen card, in pixels: the drawing grows or shrinks with it.
OPENscript.js0.6The seconds a card takes to open or close its window.
PANscript.js7How quickly the camera travels along the street (more, sooner).
ROLLscript.js46How far the van and the bike roll while they brake, in pixels (0: they wait at their place).
SWAYscript.js1How much the body, the rider and the plant rock when braking.
data-sayindex.htmlArrives by {date}, Arrives {date}, Ready today, {date}The line under the cards for each choice; {date} becomes the day, such as Wednesday 14 October.
data-daysindex.html5, 1, 0In how many days each choice arrives (with data-working="true" only working days count).

Try them in the Playground

When to use it

For the delivery choice in a basket or a checkout, or for any choice between two or three ways of doing the same thing where each way is a place or a vehicle: picking up in the shop or delivery to the door, a table on the terrace or inside, the train or the coach. The window explains what each choice means without more words, and the line below says what changes. It suits a column between 360 and 480 pixels wide.

On phones

At 390 pixels the block is 358 wide, the window 346 by 120 and a little less of the street shows, with the same animations; the closed cards are 64 pixels tall and the whole card can be tapped. There is no hover, a tap chooses at once.

With reduced motion

No travelling camera and no vehicles rolling in: the old window shuts at once, the new one is already in place and its street fades in over 0.3 seconds, with the van or the bike standing still and the shop already open with the clock at four. The parcel fades in and out, the words of the line change with a fade. When the page opens the block is already in place.

Pitfalls

  • The sky came out dark grey: the gradient lives in a hidden SVG outside the street, where the street's colour variables did not reach. They are now defined on both.
  • The monstera leaves in the bike's box looked like hearts: redrawn as long paddle leaves.
  • A window a few pixels tall, at the start of opening or the end of closing, was just a dark stripe of tarmac: the window fades at both ends.
  • The vehicle following the camera's distance started from still just as it came into sight and stopped gently, without braking; with a spring it went past and came back a few pixels, as if reversing. Now it goes at a steady speed and brakes with a constant deceleration, which stops all at once and makes the body rock.
  • The awning unrolled before the camera got there and grew by only 10 pixels: now it waits until the shop is in sight and slides out of its box, cut by a clipPath with a different id in every copy of the street.
  • The line saying when compared words by position: from Arrives by to Arrives the whole date rolled. Now every word has its key and only the different ones change; without back.out the incoming words no longer bounce out of line.
  • The empty slot had a contrast of 1.9 to 1: darkened to 3.2. With the mouse over it turned into a plain square that looked like a checkbox: now it takes the shadow of the parcel.

Libraries

GSAP 3.15.0, Gabarito (font variabile) 5.3.0.

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

Testing

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