Skip to content
animorio
IT
All components

The vase in the sun

Cards, 3D, Physics, Hover, TransitionsCanvas, GSAP, CSS onlyAdvancedCompressed weight: Demo 22 KBGSAP 28 KBFreeDownload the zip

The card of a hand-blown glass vase, half full of water, on a pale table in the sun: the pointer is the sun. The vase throws a shadow in the colour of its glass and the water, a lens, gathers the light into a bright patch; the shadow is worked out by tracing rays in three colours through slices of the vase. Choosing another glass heats the vase up again, a glow climbs it from the foot and it cools into the new colour; Add to bag wraps it in bubble wrap and tapes the seam.

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 vase in the sun</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/imbue@5.3.0/opsz.css">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/hanken-grotesk@5.3.0/index.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the card of a hand-blown glass vase standing in the sun. The pointer is the sun: the vase throws a shadow in
         the colour of its glass, with the bright line of light that the water inside focuses on the table. Another
         glass heats the vase up again and it cools into the new colour; Add to bag wraps it in bubble wrap. The vase
         and the light are worked out by the script -->
    <article class="vase" aria-labelledby="vase-name" data-vase data-autoclic>
      <div class="vase__shot" data-shot>
        <canvas class="vase__canvas" role="img" aria-label="The Drift vase in sea glass, half full of water, standing in the sun on a pale table" data-canvas></canvas>
      </div>
      <div class="vase__body">
        <div class="vase__head">
          <h2 class="vase__name" id="vase-name">Drift vase</h2>
          <p class="vase__price" data-price>€68</p>
        </div>
        <p class="vase__meta">Hand-blown glass · 24 cm</p>
        <div class="glass" role="radiogroup" aria-labelledby="glass-label" data-glass>
          <p class="glass__label" id="glass-label">Glass</p>
          <p class="glass__name" aria-hidden="true" data-name>Sea glass</p>
          <div class="glass__tiles">
            <label class="tile">
              <input class="tile__input" type="radio" name="glass" value="sea" checked>
              <span class="tile__glass" aria-hidden="true"></span>
              <span class="sr">Sea glass</span>
            </label>
            <label class="tile">
              <input class="tile__input" type="radio" name="glass" value="amber">
              <span class="tile__glass" aria-hidden="true"></span>
              <span class="sr">Amber</span>
            </label>
            <label class="tile">
              <input class="tile__input" type="radio" name="glass" value="cobalt">
              <span class="tile__glass" aria-hidden="true"></span>
              <span class="sr">Cobalt</span>
            </label>
            <label class="tile">
              <input class="tile__input" type="radio" name="glass" value="smoke">
              <span class="tile__glass" aria-hidden="true"></span>
              <span class="sr">Smoke</span>
            </label>
          </div>
        </div>
        <div class="buy" data-buy>
          <button class="add" type="button" data-add>
            <span class="add__fill" aria-hidden="true" data-fill></span>
            <span class="add__icon" aria-hidden="true">
              <svg class="add__bag" viewBox="0 0 24 24" data-bag><path d="M5.6 8.4h12.8l-.9 11.2a1.2 1.2 0 0 1-1.2 1.1H7.7a1.2 1.2 0 0 1-1.2-1.1z"/><path d="M9 10.4V7.2a3 3 0 0 1 6 0v3.2"/></svg>
              <svg class="add__tick" viewBox="0 0 24 24" data-tick><path d="M5.5 12.6l4.2 4.1 8.8-9.3"/></svg>
            </span>
            <span class="add__label" data-label>Add to bag</span>
          </button>
          <button class="undo" type="button" data-undo hidden>Undo</button>
        </div>
        <p class="sr" aria-live="polite" data-live></p>
      </div>
    </article>
  </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.

39 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 vase in the sun” from Animorio and fit it into my site

What it does

On a white background a white card with round corners. At the top the picture, drawn by the script: a pale table in the sun and on it a hand-blown vase of sea green glass, shaped like a bottle and half full of water, with its long shadow to the right, green like the glass, and near the foot a bright patch where the water gathers the sun. Below: Drift vase, €68, Hand-blown glass · 24 cm, Glass and Sea glass written in its green, four tiles of glass (Sea glass, Amber, Cobalt and Smoke) casting their shadows on the card in the same light, the one chosen floating a little higher, and the dark Add to bag button with its bag. As it arrives the card rises and the vase comes out of the furnace hot: it glows orange and cools into its glass, the thin neck first and the thick foot last. The pointer over the picture is the sun: the light comes from where the pointer is, high when the pointer is near the vase and low when it is far. The shadow goes round the vase and stretches, the bright patch slides with it, the sun's glints run over the glass and, with the sun behind the vase, the glass lights up in its colour; with the sun in front, the shadow falls behind the vase and shows through the glass. The tiles' shadows follow the sun too. Leaving the picture, the sun goes slowly back to its place. Choosing another glass heats the vase up again: a yellow and orange glow climbs it from the foot and lights the table, under the glow the glass changes colour and the shadow changes colour from the foot up; then the vase cools into the new glass, the neck first and the foot last. The glass's name comes out orange too and cools into its colour. With the pointer over it, Add to bag lightens and the bag's handle lifts; pressed, it becomes Wrapping it up and fills, while a sheet of bubble wrap goes round the vase hugging its shape, its bubbles catching the sun, and two strips of paper tape close the seam; the shadow turns soft and milky, with a speck of light under every bubble. At the end the button says In your bag with a tick that draws itself, in the pale colour of the glass, and Undo appears beside it, which peels the tape off and unwraps the vase. Choosing another glass while the vase is wrapped unwraps it before heating it.

How it works

The glass, pixel by pixel

The vase is a surface of revolution seen by a camera raised 26 degrees. For every pixel the script finds the height the eye sees first (the vase's slices, ellipses laid from the lip down) and how much glass the gaze crosses: the front wall, the water or the air, then the back wall, or the thick bottom. The glass takes light away as its colour to the power of the glass crossed (Beer-Lambert): pale in the middle, deep at the edges and in the foot, never black, with a fine dark rim at the outline. It is a layer that multiplies the table behind, worked out once for each glass.

The reflections and the sun

On top, a layer that adds up at every frame in which the sun moves: the room reflected with Fresnel and a tall window on the left, the sun as a sharp glint (Blinn, exponent 900) and as a broad sheen, the reflection off the inside of the back wall, which nearly vanishes under water because glass against water reflects very little, and the glow of the glass when the sun is behind it. The light adds up in linear light, as the difference between sRGB(behind + light) and sRGB(behind): added in sRGB it would wash everything out.

The shadow, ray by ray

The vase is cut into 56 horizontal slices. In each slice 220 rays of the sun, in red, green and blue, cross the circle of glass, the water or the air and the glass again: at every surface they bend with Snell, with the index the slice shows to a ray coming down at a slant (Bravais), and lose light with Fresnel and in the glass with its colour. They reach the table after a way as long as the slice's height times the cotangent of the sun's height: where they crowd there is the water's light, where they are missing, the shadow. The three colours have slightly different indices (SPREAD) and the shadow softens with the distance (SOFT).

On the table

The slices become two small images, one that darkens the table and one that adds the gathered light, laid down with an affine transform along the direction away from the sun and squeezed by the perspective. Part of the light through the hand-blown glass (the seeds and ripples of glass made by hand) spreads inside the shadow in its colour; under the foot the shadow is cut out and the table takes the light of the thick glass. The rays are traced again only when the sun's height changes by more than a degree: their way along the table is worked out at every frame.

The glass heated again

Every height of the vase has its own temperature. Choosing a glass, a front climbs from the foot in HEAT[0] seconds: behind it the glass is hot along a ramp, and where the front has just passed the colour becomes the new one, hidden by the glow. Then every height cools exponentially, faster where the glass is thin, and the glow's colour comes from a scale running from dark red to yellow white, stronger where the gaze crosses more glass. The table round it takes the warm light.

The bubble wrap

A sheet that follows the vase's profile, a little wider: its edge goes round from right to left, then the sheet's end comes back to the seam and two strips of tape close it, in WRAP seconds. The bubbles are a hexagonal lattice on the surface, the same size at every height, drawn all together in a few paths; each has the sun's glint where its dome faces halfway between the sun and the eye. The shadow turns milky and takes a speck of light for each bubble.

Values to change

NameFileDefaultWhat it changes
SUNscript.js[232, 27]Where the sun stands when nobody points: round the vase in degrees (0 in front, 90 right, 180 behind), and how high.
HEIGHTscript.js[17, 66]How high the sun goes, in degrees: with the pointer far from the vase, and right over it.
FOLLOWscript.js[34, 0.9]The spring that takes the sun where the pointer is: how stiff, and how much it is held back (1 = no bounce).
WATERscript.js0.62How full of water the vase is, from 0 to 1: the water is the lens that gathers the light.
SPREADscript.js3How far the glass and the water split the light into colours (1 = as much as real glass).
SOFTscript.js1.2How big the sun is, in degrees: the bigger, the softer the shadows.
HEATscript.js[0.55, 1.7]Changing glass: the seconds the glow takes to climb the vase, and the vase to cool down.
WRAPscript.js1.25The seconds the bubble wrap takes to go round the vase and have its seam taped.
WORDSscript.js['Wrapping it up', 'In your bag']The button's words while the vase is being wrapped, and after.

Try them in the Playground

When to use it

For the card of a glass or crystal product in an online shop: a vase, a carafe, a tumbler, a bottle, a lamp; wherever a clear object has colours to choose from and deserves to be seen in real light, and for the moment it goes into the bag.

On phones

The card is 340 pixels wide, or the screen minus 32, and the picture is drawn again at the real size. A finger resting on the picture puts the sun there, and sliding it sideways the sun follows: the picture has touch-action: pan-y, so up and down the page scrolls. Let go, the sun stays where the finger left it. The tiles are 44 pixels and the buttons 50 high.

With reduced motion

The sun stays put and does not follow the pointer, and the vase does not arrive hot. Changing glass, the new colour comes in a fade, with no glow; the bubble wrap comes and goes in a fade, without going round; the chosen tile is already up, without rising, and the button's words change in a fade.

Pitfalls

  • With the Bravais index the water is a strong lens: it gathers nearly all the light into a patch just past the foot, and the rest of the shadow stayed grey, lit only by the bluish sky. Coloured glass is known by its shadow: less skylight, and part of the light scattered by the seeds of hand-blown glass, in its colour, inside the shadow.
  • The little light the lens spreads round the shadow made a pale band with hard edges where the shadow's image ended: the image is wider, the extra light only counts above a soft threshold and fades towards the edges.
  • Under the foot the table, seen through the thick glass, had the shadow of the foot's own slices, a dark band that dirtied the bottom: the shadow is cut out under the foot (an evenodd clip) and there the table takes the glass's coloured light.
  • The hot front moves a step per frame, and the glow came in horizontal stripes: behind the front the glass is hot along a smooth ramp.
  • The orange glow of the cooling foot, over cobalt glass, turned magenta: the foot cools a little faster and the tail of the glow's scale is a dark brown.
  • With the sun following the pointer over the whole page, as soon as you went down to choose a glass the sun ended up in front of the vase and the shadow vanished behind it: the sun follows the pointer only over the picture and, leaving it, goes back to its place.
  • Tracing 37,000 rays at every frame cost too much: the index a slice shows changes little with the sun's height, so the rays are traced again only beyond a degree, their way along the table is scaled at every frame and each ray's weight in the glass is worked out again only when its slice changes glass.
  • Adding the reflections in sRGB with the lighter composite washed the glass out: the light added is the difference between sRGB(behind + light) and sRGB(behind), with what is behind estimated from the table seen through the glass.

Libraries

GSAP 3.15.0, Imbue (font variabile) 5.3.0, Hanken Grotesk (font variabile) 5.3.0.

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

Testing

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