Skip to content
animorio
IT
All components

The cocktail card

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

The card of a cocktail recipe, with a bar lit from behind: with the pointer over the picture the shaker rises, shakes until the steel frosts over and pours the drink over the ice, which floats up; then a jigger sinks the grenadine, which falls through the drink in wisps and settles at the bottom in a red layer that fades like a sunset, while the froth rises to the top. Every line of the ingredients fills in its colour as it goes into the glass. A click turns the card over to show the method.

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 cocktail card</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource/instrument-serif@5.3.0/400-italic.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 class="stage">
    <!-- the card of a cocktail recipe. With the pointer over the picture (or a tap) the shaker gets to work: it shakes
         until it frosts over, pours the drink over the ice, and a jigger sinks the grenadine, which falls through the
         drink and settles at the bottom in a red layer. A click turns the card over and shows the method. The bar,
         the glass, the drink, the ice and the tools are drawn by the script -->
    <article class="drink" aria-labelledby="drink-name" data-drink data-autoclic>
      <div class="drink__turn" data-turn>
        <section class="face face--front" data-front>
          <button class="shot" type="button" aria-label="Mix the drink" data-shot>
            <canvas class="shot__canvas" aria-hidden="true" data-canvas></canvas>
          </button>
          <div class="face__body">
            <p class="drink__kind">Tequila · Shaken · Highball</p>
            <div class="drink__head">
              <h2 class="drink__name" id="drink-name">Last Light</h2>
              <p class="drink__abv">12% ABV</p>
            </div>
            <ul class="pour" aria-label="Ingredients">
              <li class="pour__row" style="--tint: var(--tequila)" data-row="shaker"><span class="pour__name">Tequila blanco</span><span class="pour__ml">45 ml</span><span class="pour__line" aria-hidden="true"><span class="pour__fill" data-fill></span></span></li>
              <li class="pour__row" style="--tint: var(--blood)" data-row="shaker"><span class="pour__name">Blood orange</span><span class="pour__ml">60 ml</span><span class="pour__line" aria-hidden="true"><span class="pour__fill" data-fill></span></span></li>
              <li class="pour__row" style="--tint: var(--lime)" data-row="shaker"><span class="pour__name">Lime</span><span class="pour__ml">15 ml</span><span class="pour__line" aria-hidden="true"><span class="pour__fill" data-fill></span></span></li>
              <li class="pour__row" style="--tint: var(--grenadine)" data-row="jigger"><span class="pour__name">Grenadine</span><span class="pour__ml">10 ml</span><span class="pour__line" aria-hidden="true"><span class="pour__fill" data-fill></span></span></li>
            </ul>
            <div class="drink__foot">
              <p class="drink__time">Ice · 4 min</p>
              <button class="pill pill--line" type="button" data-flip>
                <span class="pill__icon" aria-hidden="true">
                  <svg viewBox="0 0 24 24"><path d="M4.5 9.5a8 8 0 0 1 14.2-2.6"/><path d="M19.3 3.6v3.7h-3.7"/><path d="M19.5 14.5a8 8 0 0 1-14.2 2.6"/><path d="M4.7 20.4v-3.7h3.7"/></svg>
                </span>
                <span class="pill__label">Method</span>
              </button>
            </div>
          </div>
        </section>

        <section class="face face--back" aria-label="Method" data-back>
          <p class="drink__kind">Method</p>
          <h3 class="back__name">Last Light</h3>
          <ol class="steps">
            <li class="step">
              <svg class="step__icon" viewBox="0 0 32 32" aria-hidden="true"><path d="M11 29h10l2-17H9z"/><path d="M9 12h14"/><path d="M10.5 12l2-4.5h7l2 4.5"/><path d="M13.5 7.5V4.5h5v3"/><path d="M5 15.5l-2-1.2M5 19l-2.4.2M27 15.5l2-1.2M27 19l2.4.2"/></svg>
              <div><p class="step__verb">Shake</p><p class="step__text">Tequila, blood orange and lime on ice, hard, for twelve seconds, until the tin frosts.</p></div>
            </li>
            <li class="step">
              <svg class="step__icon" viewBox="0 0 32 32" aria-hidden="true"><path d="M7 7h18l-2 22H9z"/><path d="M10 13l3 2 3-2 3 2 3-2"/><path d="M14 4.5c1-1.4 3-1.4 4 0"/></svg>
              <div><p class="step__verb">Strain</p><p class="step__text">Over fresh ice, into a chilled highball.</p></div>
            </li>
            <li class="step">
              <svg class="step__icon" viewBox="0 0 32 32" aria-hidden="true"><path d="M10 3h12l-4.5 9h-3z"/><path d="M14.5 12l-4.5 9h12l-4.5-9"/><path d="M16 23v6"/><path d="M13 28.5c1 .8 5 .8 6 0"/></svg>
              <div><p class="step__verb">Sink</p><p class="step__text">Pour the grenadine down the side. It finds the bottom by itself.</p></div>
            </li>
            <li class="step">
              <svg class="step__icon" viewBox="0 0 32 32" aria-hidden="true"><circle cx="16" cy="16" r="11"/><circle cx="16" cy="16" r="7.5"/><path d="M16 8.5v15M8.5 16h15M10.7 10.7l10.6 10.6M21.3 10.7L10.7 21.3"/></svg>
              <div><p class="step__verb">Garnish</p><p class="step__text">A blood orange wheel on the rim. Do not stir: the sun sets in the glass.</p></div>
            </li>
          </ol>
          <dl class="facts">
            <div><dt>Glass</dt><dd>Highball</dd></div>
            <div><dt>Ice</dt><dd>Cubed</dd></div>
            <div><dt>Time</dt><dd>4 min</dd></div>
          </dl>
          <button class="pill pill--full" type="button" data-unflip>
            <span class="pill__icon" aria-hidden="true">
              <svg viewBox="0 0 24 24"><path d="M9.5 6.5L4.5 11.5l5 5"/><path d="M4.8 11.5h9.7a5 5 0 0 1 0 10H12"/></svg>
            </span>
            <span class="pill__label">Back to the glass</span>
          </button>
        </section>
      </div>
      <p class="sr" aria-live="polite" data-live></p>
    </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.

54 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 cocktail card” from Animorio and fit it into my site

What it does

On a black background a warm near-black card with round corners. At the top the picture, drawn by the script: a dark wall with an amber light behind it, the edge of a shelf, a dark stone bar top that mirrors what stands on it; on the left a glass highball with three ice cubes at the bottom, on the right a steel shaker standing up. Below: Tequila · Shaken · Highball, the name Last Light in italics with 12% ABV, four ingredients with their measures (Tequila blanco 45 ml, Blood orange 60 ml, Lime 15 ml, Grenadine 10 ml), each with a thin line under it, then Ice · 4 min and the Method pill. With the pointer over the picture, or a tap, the shaker rises and shakes up and down, tilting, while the steel frosts over; then it loses its cap, which flies off, leans over the glass and pours: the apricot drink falls in a thread that thins as it speeds up, and the surface waves where it lands. The level rises, the cubes leave the bottom and float up, knocking into each other and turning until they sit square, and the froth of the shaking rises to the top in a pale layer. As it pours, the tequila, blood orange and lime lines fill with their colours. The shaker goes back to its place with its cap and lands with a little bounce; a jigger full of grenadine comes in, tips and pours it down the side of the glass: the grenadine falls through the drink in wisps and settles at the bottom, spreads out and makes a flat red layer that fades up into the orange like a sunset, and its line turns red. Last, a blood orange wheel drops onto the rim with a bounce. On the bar, in front of the glass, the light through the drink leaves a patch of its colour. A click on the card (or on the Method pill) turns it over on a spring and shows the back: Method, the name, four steps with a drawn icon and a verb (Shake, Strain, Sink, Garnish), three facts (glass, ice, time) and the orange Back to the glass pill. Turned back again, the glass is empty and ready for another round.

How it works

The layers sort themselves

The drink lives on a grid of 2 pixel cells, columns across the glass and rows up from the floor; every cell holds a share of grenadine and a share of froth, the rest is the drink. Every frame the grenadine moves into the cell below, but only into the room that cell has left, and the froth rises the same way into the one above; a cell resting on something full moves towards the mean of the cells of its row that rest too, so a pile flattens at once like a liquid. What comes out is a flat red layer at the bottom and a pale one on top, without anyone saying where they go: only the weight decides.

The pouring thread

The shaker and the jigger are moved by a GSAP timeline; their spouts are found by turning a point of the drawing with their pose. Particles leave from there with the spout's own speed and the speed of the pour, spread over the frame as if they had left one after another, and fall under gravity. Those that left within a fortieth of a second of each other join into a thread, the narrower the faster they go (the same flow through a thinner thread); further apart they become drops. Reaching the surface they add their volume: the level comes from a table that sums the circles of the glass, which narrows towards the foot.

Ice and waves

The cubes are rigid bodies in steps of 1/240 of a second: weight, a buoyancy as strong as they are deep, a stronger drag in the drink, knocks against each other and against the sloping walls, and a torque that turns them until a face is up. The surface is a wave equation with one column per cell: the thread and the grenadine push it where they land, and the cubes bobbing up and down move it; the waves bend the front edge of the surface, its ellipse seen from above and the line the cubes float on.

The light through the drink

Every pixel of the liquid knows how high it stands over the floor, measured along the arc of the perspective, so flat layers look curved as in a real glass. Its colour mixes the drink, the grenadine and the froth in their shares; the grenadine tints far more than its share, and every pixel also takes some of the red of the cells below it, which fades upwards like a sunset. The drink's colour is the mean of the ingredients' colours in :root, weighed by the measures written on the card. Over it, a light through the middle, the dark edges of the glass, the strips of light, the coloured patch on the bar and the upside down reflection of it all.

The card that turns

The two faces share one cell of a grid, the second turned by 180 degrees with backface-visibility hidden; GSAP turns the card with a back.out and shrinks it a little half way. The script also hides the face that cannot be seen the moment the card is edge on (Safari does not always do it by itself) and makes the far one inert, moving the focus to the other face's button when it was needed. Turned back, the glass is emptied while it faces away: it arrives empty and ready for another round.

The states, and rest

The drink is made with the mouse over the picture, a tap, or Enter on the picture (it is a button); a click on the card once the drink is ready turns it, and Method and Back to the glass always do. An aria-live status says Shaking, Pouring, Sinking the grenadine, the drink is ready, Method and Ingredients. The time step is limited to 1/30 of a second; the grid sleeps once it has moved nothing for half a second, the waves under a threshold of energy, the cubes once they are still: then nothing is drawn any more.

Values to change

NameFileDefaultWhat it changes
SHAKEscript.js1The seconds the shaker shakes.
RATTLEscript.js7How many times a second it goes up and down while shaking.
POURscript.js1.4The seconds it takes to pour the drink.
SINKscript.js110How fast the grenadine falls through the drink, in pixels a second.
FROTHscript.js1How much froth the shaking leaves on top, from 0 to 2.
ICEscript.js3How many cubes of ice are in the glass, from 0 to 4.
SLOSHscript.js1How much the surface waves where the stream lands, from 0 to 2.
TURNscript.js1.1The seconds the card takes to turn over.

Try them in the Playground

When to use it

For a cocktail recipe on a recipe site, in a cocktail bar's menu or on the page of a spirit; wherever a drink is best understood seen being made (an iced coffee, a smoothie, a layered iced tea), and for a card that needs two faces, the product in front and the instructions behind.

On phones

The card is 340 pixels wide, or the screen minus 32, and the scene is drawn again at the real size. A phone has no mouse passing over: a tap on the picture makes the drink, another tap once it is ready turns the card, and a tap on the back turns it again. The simulation is the same as on a computer: the grid is 44 by 65 cells and the liquid is painted into a picture of 88 by 149 pixels, scaled up.

With reduced motion

The shaker does not move or pour: the finished drink, with its layers, the ice afloat and the wheel on the rim, comes in with a fade over the empty glass, and the ingredients' lines fill at once. The card does not turn: it fades and comes back with the other face. The pills do not swell.

Pitfalls

  • The grenadine falling down one side made a heap at the bottom that never flattened: levelling between neighbouring cells, in pairs, took tens of seconds to cross the glass. Now every cell resting on something moves towards the mean of all the cells of its row that rest too; but that alone was not enough, since a column of red resting only on itself stayed standing: a heap also runs off sideways, six times a frame, into the cells beside it, where it sinks again if there is room below, and the layer is flat in a little over a second.
  • The pouring thread broke into dots half way down: the particles that left in the same frame all started from the same point and, fast, drifted further apart than the fixed distance that joined them. Now they leave spread over the frame, already carried forward by the time they would have had, and they are joined by when they left, not by how far apart they are.
  • At the start of the pour the thread zig-zagged: it began while the shaker was still finishing its tilt, at its fastest, and took half of that speed. Now the pour begins once the tilt is over and takes only a fifth of the spout's speed.
  • The red layer ended sharp, a straight line between red and orange. Every pixel now also takes a share of the red of the nine cells below it, falling with the distance: the layer fades upwards like a sunset.
  • Frost made of pale specks looked like gravel on the shaker: now it is a haze with a very fine grain and a few runs of melt.
  • The reflection on the bar was drawn flipped over the board's scale and landed in the wrong place: now it is the objects' canvas drawn upside down in real pixels around the line they stand on, clipped to the bar and faded.
  • In the preview video the second click did not turn the card: it came when the timeline had a few hundredths of a second left, before its onComplete, and the drink was still being made. Now the drink is ready through a call inside the timeline, as the wheel lands, and the timeline runs on a little while the last red wisps reach the bottom; the wheel comes later, so the picture keeps moving until the layer is flat.

Libraries

GSAP 3.15.0, Instrument Serif 5.3.0, Mona Sans (font variabile) 5.3.0.

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

Testing

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