
Tiles that rise
SVG, Hover, Physics
NewFree
A house of playing cards builds itself, card by card, with the cards gliding in and leaning on each other in pairs with a tremble; a click or a puff of the pointer brings it down with real physics, the cards pile up and then the house builds itself again.
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 house of cards</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bodoni-moda@5.3.0/index.css">
<link rel="stylesheet" href="style.css">
</head>
<body>
<main class="scena" data-stage data-autoclic tabindex="0" role="button" aria-label="A house of cards: click to knock it down">
<!-- the drawings every card uses: the back of the deck and four fronts, drawn upright and turned to fit the card -->
<svg class="disegni" aria-hidden="true" xmlns="http://www.w3.org/2000/svg">
<defs>
<pattern id="lattice" patternUnits="userSpaceOnUse" width="8" height="8" patternTransform="rotate(45)">
<path class="dorso-rete" d="M0 0V8M0 0H8" />
</pattern>
<path id="pip-heart" d="M0 8C-9 1-11-4-11-7C-11-11-8-13-5.5-13C-3-13-1-11.5 0-9.5C1-11.5 3-13 5.5-13C8-13 11-11 11-7C11-4 9 1 0 8Z" />
<path id="pip-diamond" d="M0-12C2.6-7 5.6-3 8.4 0C5.6 3 2.6 7 0 12C-2.6 7-5.6 3-8.4 0C-5.6-3-2.6-7 0-12Z" />
<path id="pip-spade" d="M0-13C-9-5-11 0-11 3C-11 7-8 9-5.5 9C-3.6 9-2 8-1.2 6.6C-1.4 9-2.6 11.2-4.6 12.6H4.6C2.6 11.2 1.4 9 1.2 6.6C2 8 3.6 9 5.5 9C8 9 11 7 11 3C11 0 9-5 0-13Z" />
<path id="pip-club" d="M0-13C3.4-13 5.8-10.4 5.8-7.2C5.8-5.8 5.4-4.6 4.6-3.6C5.2-3.8 5.8-3.9 6.4-3.9C9.6-3.9 12-1.4 12 1.8C12 5 9.6 7.6 6.4 7.6C4.4 7.6 2.6 6.6 1.6 5C1.8 8.2 2.8 10.8 4.6 12.6H-4.6C-2.8 10.8-1.8 8.2-1.6 5C-2.6 6.6-4.4 7.6-6.4 7.6C-9.6 7.6-12 5-12 1.8C-12-1.4-9.6-3.9-6.4-3.9C-5.8-3.9-5.2-3.8-4.6-3.6C-5.4-4.6-5.8-5.8-5.8-7.2C-5.8-10.4-3.4-13 0-13Z" />
<path id="star" d="M0-6C.8-1.6 1.6-.8 6 0C1.6.8.8 1.6 0 6C-.8 1.6-1.6.8-6 0C-1.6-.8-.8-1.6 0-6Z" />
<!-- the back of the deck: a lattice, a frame, and a moon with a star in an oval -->
<symbol id="back" viewBox="0 0 100 70">
<g transform="translate(100 0) rotate(90)">
<rect class="dorso-carta" width="70" height="100" rx="5" />
<rect class="dorso" x="4" y="4" width="62" height="92" rx="3" />
<rect fill="url(#lattice)" x="7" y="7" width="56" height="86" rx="2" />
<rect class="dorso-filo" x="7" y="7" width="56" height="86" rx="2" />
<rect class="dorso-filo dorso-filo--fine" x="9.5" y="9.5" width="51" height="81" rx="1.5" />
<ellipse class="dorso dorso-filo" cx="35" cy="50" rx="17" ry="23" />
<ellipse class="dorso-filo dorso-filo--fine" cx="35" cy="50" rx="14" ry="20" />
<path class="dorso-oro" d="M39.5 37.5C33 37.5 28.5 43 28.5 49.5C28.5 56 33 61.5 39.5 61.5C36.6 62.8 33.4 63.2 30.2 62C25.4 60 22.6 55 22.6 49.5C22.6 44 25.4 39 30.2 37C33.4 35.8 36.6 36.2 39.5 37.5Z" />
<use class="dorso-oro" href="#star" transform="translate(41 47) scale(.9)" />
<use class="dorso-oro" href="#star" transform="translate(44.5 57) scale(.45)" />
<use class="dorso-oro" href="#star" transform="translate(14 14) scale(.55)" />
<use class="dorso-oro" href="#star" transform="translate(56 14) scale(.55)" />
<use class="dorso-oro" href="#star" transform="translate(14 86) scale(.55)" />
<use class="dorso-oro" href="#star" transform="translate(56 86) scale(.55)" />
</g>
</symbol>
<!-- four fronts: an ace and three court letters, each with one big pip -->
<symbol id="front-a" viewBox="0 0 100 70">
<g transform="translate(100 0) rotate(90)">
<rect class="fronte" width="70" height="100" rx="5" />
<rect class="fronte-filo" x="3.5" y="3.5" width="63" height="93" rx="3" />
<use class="seme-nero" href="#pip-spade" transform="translate(35 50) scale(1.55)" />
<text class="indice seme-nero" x="9" y="16">A</text>
<use class="seme-nero" href="#pip-spade" transform="translate(10.5 24) scale(.32)" />
<g transform="rotate(180 35 50)">
<text class="indice seme-nero" x="9" y="16">A</text>
<use class="seme-nero" href="#pip-spade" transform="translate(10.5 24) scale(.32)" />
</g>
</g>
</symbol>
<symbol id="front-k" viewBox="0 0 100 70">
<g transform="translate(100 0) rotate(90)">
<rect class="fronte" width="70" height="100" rx="5" />
<rect class="fronte-filo" x="3.5" y="3.5" width="63" height="93" rx="3" />
<use class="seme-rosso" href="#pip-heart" transform="translate(35 51) scale(1.5)" />
<text class="indice seme-rosso" x="9" y="16">K</text>
<use class="seme-rosso" href="#pip-heart" transform="translate(10.5 24) scale(.32)" />
<g transform="rotate(180 35 50)">
<text class="indice seme-rosso" x="9" y="16">K</text>
<use class="seme-rosso" href="#pip-heart" transform="translate(10.5 24) scale(.32)" />
</g>
</g>
</symbol>
<symbol id="front-q" viewBox="0 0 100 70">
<g transform="translate(100 0) rotate(90)">
<rect class="fronte" width="70" height="100" rx="5" />
<rect class="fronte-filo" x="3.5" y="3.5" width="63" height="93" rx="3" />
<use class="seme-rosso" href="#pip-diamond" transform="translate(35 50) scale(1.6)" />
<text class="indice seme-rosso" x="9" y="16">Q</text>
<use class="seme-rosso" href="#pip-diamond" transform="translate(10.5 24) scale(.32)" />
<g transform="rotate(180 35 50)">
<text class="indice seme-rosso" x="9" y="16">Q</text>
<use class="seme-rosso" href="#pip-diamond" transform="translate(10.5 24) scale(.32)" />
</g>
</g>
</symbol>
<symbol id="front-j" viewBox="0 0 100 70">
<g transform="translate(100 0) rotate(90)">
<rect class="fronte" width="70" height="100" rx="5" />
<rect class="fronte-filo" x="3.5" y="3.5" width="63" height="93" rx="3" />
<use class="seme-nero" href="#pip-club" transform="translate(35 50) scale(1.45)" />
<text class="indice seme-nero" x="9" y="16">J</text>
<use class="seme-nero" href="#pip-club" transform="translate(10.5 24) scale(.32)" />
<g transform="rotate(180 35 50)">
<text class="indice seme-nero" x="9" y="16">J</text>
<use class="seme-nero" href="#pip-club" transform="translate(10.5 24) scale(.32)" />
</g>
</g>
</symbol>
</defs>
</svg>
<header class="testa">
<p class="sopra" data-head>Ottoline Vane presents</p>
<h1 class="titolo" data-head>The House of Cards</h1>
</header>
<!-- the table, turned a little so the backs of the cards show; the script deals the cards onto it -->
<div class="palco" data-view>
<div class="mondo" data-world>
<div class="tavolo" data-table></div>
</div>
</div>
<!-- the puff of air that knocks it down -->
<svg class="soffio" data-gusts aria-hidden="true" xmlns="http://www.w3.org/2000/svg"></svg>
<p class="nota" aria-live="polite"><span data-hint>Dealing the house</span></p>
</main>
<script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.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.
25 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 house of cards” from Animorio and fit it into my siteThe table and the cards live in a CSS 3D world: a container with transform-style preserve-3d, turned with rotateX and rotateY inside a stage with perspective. Every card is a div as long as the card and as deep as it is wide, with two faces back to back (backface-visibility hidden): rotate gives the card its lean, rotateX(90deg) stands it on its edge, so the back shows at three quarters. The drawings (back, ace and court cards, suits) are SVG symbols of our own, placed with use.
Every card is an object with x, y, z, lean and opacity: GSAP moves those numbers, the physics overwrites them, and on every tick of the ticker a single function copies them into the transforms. Under every card lies a shadow on the felt, as wide as the card seen from above and fainter the higher the card is; and an upright card is darker than one lying flat, which catches the light of the lamp.
The places in the house are worked out in card lengths: the lean decides how far apart the feet of a pair are, the flat card rests on the two nearby tips, the next storey stands on it. Every card arrives with a timeline: x through keyframes that swing to the side, y slowing down, the lean rocking and dying away. The two cards of a pair stop a moment above their place, drop together and tremble with small keyframes around the right pose.
On the click every card becomes a thin rectangle in Matter.js, held still (static) where it is. The cards are let go in a wave, the nearest to the hit first, with a shove that gets weaker with distance but is never zero, so the whole thing comes down. The felt is slippery at first, then grips and the pile stays put. On every step the speed across the card is braked and the speed along it is not: a card lying flat falls slowly and glides sideways, like real ones.
A quick sweep of the mouse over the house (more than 2.6 pixels per millisecond) does the same as a click, in the direction of the movement; a slow one only makes it lean. The physics moves in fixed steps of 1/120 of a second, and when the cards are still (or after a few seconds) the Matter world is emptied. A moment later a new timeline lifts each card out of the pile towards us and brings it back to its place with the same flight as the first time, faster.
| Name | File | Default | What it changes |
|---|---|---|---|
LEVELS | script.js | 4 | The storeys of the house, 2 to 5: four storeys take twenty-six cards. |
LEAN | script.js | 18 | How many degrees each card leans from upright. |
DEAL_SPEED / FLUTTER | script.js | 1 / 1 | The speed of the building and how much the cards rock as they glide. |
BLOW / SLIDE | script.js | 1 / 0.03 | The strength of the blow and how slippery the felt is while it falls. |
REST | script.js | 1.6 | The seconds the pile lies there before the house builds itself again. |
TURN | script.js | 28 | How many degrees the table is turned, to show the backs of the cards. |
--back, --gold, --felt | style.css | #8f1f2c, #e7c47a, #1d5446 | The back of the cards, the gold of the drawings and the felt of the table. |
For the page of a magician, a board-game club or a card room, for a 404 page (everything fell down here) or a page about fragility and risk. It is a toy to watch: the real content goes next to it.
The same animations and the same physics: the cards are sized to the screen, so on a phone the house fits in width and in height. The puff is mouse only; with a finger a tap is enough.
The house is already built. A click fades it out and the pile appears in its place, already still (the physics is worked out all at once); the next click, again with a fade, brings the house back.
GSAP 3.15.0, Matter.js 0.20.0, Bodoni Moda (font variabile) 5.3.0.
Compressed with gzip, the three demo files weigh 11 KB; the libraries: GSAP 28 KB, Matter.js 25 KB.
Tested on 10 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.