Skip to content
animorio
IT
Back to the library

Cards laid on the table

Hover, TextGSAP, CSS onlyMediumCompressed weight: Demo 8.9 KBGSAP 28 KBFreeDownload the zip

Minimal style: five white cards with a hairline edge, squared in a stack, a word in the corner of each. As the pointer comes near, the deck spreads sideways in a row like cards laid on a table, each on its own spring and a moment after the one before, until the words read as a sentence; the card under the pointer lifts a few pixels and takes the red. Far away, the cards gather up and the stack squares itself with a last small tap.

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>Cards laid on the table</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/archivo@5.3.0/wdth.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage" data-stage>
    <!-- the sentence people read; the cards below are only its picture -->
    <h1 class="sr" data-read>Lay your cards on the table.</h1>

    <!-- five white cards squared in a stack, one word in the corner of each. As the pointer (or a finger) comes close,
         the deck spreads sideways like cards laid on a table, every card on a spring of its own and a moment after
         the one before; the card under the pointer lifts a few pixels and takes the accent. Far away, the deck
         gathers back into a stack and squares up with a last small tap -->
    <div class="table" aria-hidden="true" data-table>
      <div class="ruler" data-ruler>
        <i class="ruler__line" data-line></i>
      </div>
      <div class="deck" data-deck></div>
    </div>

    <!-- the same thing for the keyboard: focus spreads the deck, the arrows move from card to card -->
    <div class="handle" role="slider" tabindex="0" aria-label="Cards on the table" aria-valuemin="1" aria-valuemax="5" aria-valuenow="1" data-handle></div>

    <p class="note" aria-hidden="true" data-note>
      <span class="note__rule"></span>
      <span class="note__hint" data-hint>Move closer</span>
      <span class="note__rule"></span>
    </p>

    <!-- an invisible word, to measure how wide the words are -->
    <span class="probe" aria-hidden="true" data-probe></span>
  </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.

19 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 “Cards laid on the table” from Animorio and fit it into my site

What it does

On a warm white, a stack of five white cards with a one-pixel edge: you see the top card, with “Lay” in its top right corner, and below and to the right the edges of the others, a pixel and a half apart like a real deck. Under the stack runs a thin ruler with a tick at each end. On arrival the cards drop onto the table one after the other, the lowest first, and the stack squares itself with a small tap. As the pointer comes near, the deck spreads the way a hand spreads it on a table: the stack slides to the start of the row and the cards come out from under it one after the other, each on its own spring, one pixel too far and back. Every card leaves a strip of the one below uncovered, and the words in the corners read in a row: “Lay your cards on the table.”. While a card runs its word narrows on the width axis, and widens again when it stops. The card under the pointer lifts a few pixels with a small bounce, its edge and its word turn red, the word gains weight and the line under it lengthens; on the ruler its tick grows and turns red. The ruler follows the row, with a tick at the right edge of every card. When the pointer moves away the cards gather up starting from the last one, the stack goes back to the middle and, once it is still, squares itself with a last small tap: the edges underneath open by a hair and close again, and the ticks of the ruler hop.

How it works

Five cards and a ruler

The cards are made by the script, one for every word in WORDS: a div the script moves and, inside it, a face with a white fill, an edge made with a one-pixel inset box-shadow, the word in the top right corner and a thin line under it. The first card lies on top of all the others (highest z-index) and each one leaves the right strip of the card below uncovered: that is where the word sits. The ruler is a one-pixel line stretched with scaleX and one tick per card stretched with scaleY, so they only move with transform.

How near the pointer is

On every frame the script measures the distance between the pointer and the rectangle the cards cover at that moment, and turns it into a wish from 0 (closed) to 1 (open) with a soft curve: open within a third of REACH, closed beyond REACH. Since the rectangle grows as the deck opens, a stack that starts to open comes closer to the pointer by itself and opens all the way, and one that starts to close closes all the way: no cards left halfway, trembling on the border.

A moment after the other

The script keeps the wishes of the last half second with their time. Every card reads the wish from DELAY seconds ago multiplied by its place: opening, the first to move is the whole stack, which slides to the start of the row, then the cards come out from under it from the second to the last; closing, the order is reversed, the last card comes back first and the stack goes back to the middle last. The position of a card is (i × q − half × g) × the strip, where q is how far it has come out and g how far the stack has slid: at rest the row is always centred.

One spring per card

Every card has its own damped spring, a little softer than the one above, chasing its wish; gsap.ticker moves it forward in small steps of 1/240 of a second, so it stays steady even when a frame comes late. BOUNCE lowers the damping: at 0.4 the card goes a couple of pixels too far and comes back. The speed of the spring also narrows the word while it runs (the wdth axis of Archivo, down to 76).

The card under the pointer and the last tap

The card under the pointer is the first from the top whose rectangle holds it, without its lift, so it does not slip from under the pointer as it rises. It has a second, livelier spring that lifts it by LIFT pixels, and an accent from 0 to 1 that fades quickly: edge, word, line and tick go from ink to red, and the word goes from 380 to WEIGHT. When the deck is closed again a GSAP tween takes a number from 1 to 0 with elastic.out: the thickness of the stack and the ticks follow it, and the stack squares itself.

Values to change

NameFileDefaultWhat it changes
WORDSscript.js['Lay', 'your', 'cards', 'on the', 'table.']The words: one card per word, from 2 to 7. The first lies on top of the stack. Short words, since each one has to fit its strip.
REACHscript.js200How near the pointer has to come, in pixels from the edge of the cards, for the deck to spread (70% on a phone).
STEPscript.js0.74How much of every card the next one leaves uncovered, as a share of its width: 0.4 a tight deck, 1 the cards side by side.
DELAYscript.js0.06How long every card waits after the one before, in seconds: 0 they all start together.
BOUNCEscript.js0.4How far the cards go past their place before they settle: 0 not at all, 1 a small bounce.
LIFTscript.js8How many pixels the card under the pointer lifts.
WEIGHTscript.js680The weight of the word on the card under the pointer, from 300 to 900; the others weigh 380.
SPEEDscript.js1The speed of the springs: 2 is twice as fast, 0.5 half as fast.

Try them in the Playground

When to use it

For a few words revealed as you come closer: a tagline on a launch page, the services of a studio, the courses of a tasting menu, the days of a festival, the steps of a method. It works with short words and three to seven cards; for long sentences plain text is better.

On phones

The same, with smaller cards so the open row fits the width of the screen: a finger touching near the cards spreads them, the card under the finger lifts, and a moment after the finger lifts the deck closes again.

With reduced motion

No movement: the row is already laid out in its place and fades in; the card under the pointer does not lift, it only takes the red and the weight with a fade.

Pitfalls

  • On arrival the cards fade in, and a half see-through card showed the words of the cards below it: the covered words stay hidden until the arrival is over.
  • In the closed stack the ruler ticks of all the cards fell on the same spot and made a dark smudge: the ticks of the cards still in the stack fade away and only the two at the ends remain.

Libraries

GSAP 3.15.0, Archivo (font variabile, assi wdth e wght) 5.3.0.

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

Testing

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