01 — Flips

Flip Card

Hover to flip a card and reveal its back. Two faces sit in the same place; backface-visibility: hidden hides the one pointing away so you only see one at a time.

preserve-3d + rotateY + backface-visibility FLIP
mountains
Mountain Trail
Sunrise, 6:04am
A 14-mile loop with 3,200 ft of elevation gain. Start at the lower trailhead before dawn.
plated food
Hand-rolled Pasta
Chef's special
Semolina & egg, tossed with brown butter, crispy sage, and a shaving of parmigiano.
<div class="flip">
  <div class="face front">Hover me</div>
  <div class="face back">You found the back!</div>
</div>
02 — Flips

Coin Flip

A continuously spinning coin — same technique as the flip card, but the rotateY is in a @keyframe so it never stops. The coin's two "sides" are circles with different gradients.

@keyframes rotateY 0 → 360 infinite FLIP
$
2026
<div class="coin">
  <div class="side heads">$</div>
  <div class="side tails">2026</div>
</div>
03 — Flips

Door Open

A door swings open on hover. The trick is transform-origin: left center — this pins the rotation axis to the left edge so it hinges like a real door instead of rotating around the center.

transform-origin: left + rotateY FLIP
<div class="door-scene">
  <div class="door"></div>
</div>
04 — Solids

Rotating Cube

Six faces, one cube. Each face is a full-size absolute element translated to one of the cube's six sides. Rotating the parent spins the whole thing.

6 faces × translateZ + rotateX/Y SOLID
<div class="cube-wrap">
  <div class="cube">
    <div class="face f-front">1</div>
    <div class="face f-back">2</div>
    <div class="face f-right">3</div>
    <div class="face f-left">4</div>
    <div class="face f-top">5</div>
    <div class="face f-bottom">6</div>
  </div>
</div>
05 — Solids

Pyramid

A 4-sided pyramid built from squares clipped into triangles with clip-path. Each triangle rotates 90° from the next around the vertical axis.

clip-path triangle + rotateY stagger SOLID
<div class="pyr-wrap">
  <div class="pyr">
    <div class="face f1"></div>
    <div class="face f2"></div>
    <div class="face f3"></div>
    <div class="face f4"></div>
  </div>
</div>
06 — Solids

Rubik's Cube

A fully-built Rubik's Cube. Each of the six faces is a CSS Grid of nine colored "stickers" over a black plastic base. The whole cube spins on a continuous keyframe so you can see every side.

6 faces × 3×3 grid of stickers MODEL
<div class="rubik-wrap">
  <div class="rubik">
    <!-- 6 faces; each has 9 <span>s for stickers -->
    <div class="r-face front">
      <span></span><span></span><span></span>
      <span></span><span></span><span></span>
      <span></span><span></span><span></span>
    </div>
    <div class="r-face back"><!-- 9 spans --></div>
    <div class="r-face right"><!-- 9 spans --></div>
    <div class="r-face left"><!-- 9 spans --></div>
    <div class="r-face top"><!-- 9 spans --></div>
    <div class="r-face bottom"><!-- 9 spans --></div>
  </div>
</div>
07 — Interactive

Tilt Card

The simplest 3D effect for product cards: on hover, the card tilts slightly on two axes. Because it's on :hover, it needs no JavaScript.

:hover + rotateX + rotateY + scale HOVER

Morning light

A short caption describing this beautiful product or photograph.

Desert dusk

Tilt me on hover — I rotate in two directions at once.

<div class="tilt-wrap">
  <div class="tilt">
    <h4>Morning light</h4>
    <p>A short caption...</p>
  </div>
</div>
08 — Interactive

Card Fan

Three stacked cards fan out on hover like a hand of playing cards. Each card is absolutely positioned in the same place; hovering the parent translates and rotates each into its own spot.

stacked position:absolute + hover transforms HOVER
Coastal
Mountain
Desert
<div class="fan">
  <div class="card c1">First.</div>
  <div class="card c2">Second.</div>
  <div class="card c3">Third.</div>
</div>
09 — Interactive

3D Push Button

A hard-offset box-shadow makes a flat button look like it has a thick side. On hover it lifts, on click it presses down into its own shadow.

box-shadow offset + translateY on press HOVER
<a href="#" class="btn3d">Press me</a>
10 — Scenes

Book Open

Two layers — pages underneath, cover on top. The cover has its transform-origin set to the left edge (the spine), so rotating it opens the book just like a real one.

cover rotateY around left spine SCENE

Chapter One

The morning arrived the way mornings usually do — slowly, with the light creeping across the floor.

— 1 —

 

She put the kettle on and watched the garden through the window, the copper slowly heating behind her.

— 2 —

A Short Novel

The Quiet Hour

Ex Libris · 1998
<div class="book-wrap">
  <div class="book">

    <!-- Four layers, back to front: -->
    <div class="back-cover"></div>     <!-- rear board       -->
    <div class="page-stack"></div>     <!-- page thickness   -->

    <div class="pages">                <!-- the open spread  -->
      <div class="left-page">
        <h4>Chapter One</h4>
        <p>The morning arrived...</p>
      </div>
      <div class="right-page"><p>...continued</p></div>
    </div>

    <!-- Front cover has TWO faces so the inside of the
         cover is visible when the book is open. -->
    <div class="front-cover">
      <div class="cover-outside">
        <small>A Short Novel</small>
        <h3>The Quiet Hour</h3>
      </div>
      <div class="cover-inside">
        <small>Ex Libris</small>
      </div>
    </div>

  </div>
</div>
12 — Scenes

3D Extruded Text

A headline with depth, built entirely from stacked text-shadows. Each shadow is offset a pixel more than the last — the effect is an extruded "side" on the letters. A final rotateX adds perspective.

layered text-shadow + perspective SCENE
Go Deep.
<div class="text3d">Go Deep.</div>
13 — Models

Real 3D Model (GLB) — Damaged Helmet

CSS can fake 3D, but for anything this detailed you want a real 3D file. This is a .glb model — the 3D equivalent of a .png — loaded with Google's <model-viewer> web component. One tag, real PBR lighting, drag to rotate, scroll to zoom.

<model-viewer> + free glTF sample asset GLB
<!-- Load Google's <model-viewer> web component once, per page -->
<script type="module"
  src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.5.0/model-viewer.min.js">
</script>

<!-- Drop one tag. That's the whole component. -->
<model-viewer
  src="DamagedHelmet.glb"
  alt="A damaged sci-fi helmet"
  auto-rotate
  camera-controls
  shadow-intensity="1"
  exposure="1"
  environment-image="neutral">
</model-viewer>
14 — Models

Real 3D Model (GLB) — Astronaut

Same <model-viewer> component, different file. This one's from Google's public sample library. Drag to orbit, scroll to zoom, double-click for AR on supported devices.

interactive camera + ambient lighting GLB
<model-viewer
  src="https://modelviewer.dev/shared-assets/models/Astronaut.glb"
  alt="An astronaut"
  auto-rotate
  camera-controls
  shadow-intensity="1.2"
  exposure="0.9"
  environment-image="neutral">
</model-viewer>

<!-- Yes, that's the whole thing.
     No Three.js boilerplate required. -->
15 — Models

Product 3D — Interactive Showcase

The e-commerce pattern: a product on a soft-shadowed stage, auto-rotating by default, fully inspectable when the shopper engages. Click or drag to stop the rotation and orbit freely. Two info chips sit to the side like a product detail panel.

<model-viewer> + auto-rotate + product card layout PRODUCT
drag to inspect
New Release

Studio BoomBox ’86

A radio-cassette deck reissue. Dual speakers, telescopic antenna, leather-wrapped handle. Fully 3D-previewable above — rotate it, zoom in on the dials.

$249
Stereo · 2×3W 12hr battery
<!-- Load the web component once per page -->
<script type="module"
  src="https://ajax.googleapis.com/ajax/libs/model-viewer/3.5.0/model-viewer.min.js">
</script>

<div class="product-showcase">

  <div class="product-viewer">
    <model-viewer id="product-mv"
      src="BoomBox.glb"
      alt="BoomBox product"
      auto-rotate
      camera-controls
      shadow-intensity="1.5"
      exposure="1.2"
      environment-image="neutral"
      camera-orbit="-30deg 75deg 0.3m"
      field-of-view="30deg"></model-viewer>
    <div class="product-hint">drag to inspect</div>
  </div>

  <div class="product-info">
    <span class="product-eyebrow">New Release</span>
    <h3>Studio BoomBox '86</h3>
    <p>A radio-cassette deck reissue...</p>
    <div class="product-price">$249</div>
    <button class="btn-primary">Add to cart</button>
    <button class="btn-ghost"
      onclick="toggleSpin()">Toggle spin</button>
  </div>
</div>