Skip to main content

Command Palette

Search for a command to run...

3D Cube Flip Card Using Pure HTML & CSS

Published
4 min read

These notes explain how to build a 3D cube-style flip card step by step using only HTML and CSS, exactly like a team/people card that shows an image on the front and rotates to reveal content on hover.

This is written for future reference + blog posting (Hashnode) and focuses on why each step exists, not just what to write.


1. The Goal (Mental Model)

We are not making a normal flip card.

We are simulating a 3D cube rotation:

  • Front face → Image

  • Side face → Text (name + bio)

  • On hover → cube rotates 90° on Y-axis

Key idea:

The browser must believe the element has depth.


2. Required HTML Structure (Very Important)

<div class="card">
  <div class="card-inner">
    <div class="card-front">
      <img src="photo.png" />
    </div>
    <div class="card-side">
      <h3>Name</h3>
      <p>Description</p>
    </div>
  </div>
</div>

Why this structure?

ElementRole
.cardCamera (perspective)
.card-innerCube (rotates)
.card-frontFront face
.card-sideSide face

Never skip this nesting — 3D depends on it.


3. Card Container = Camera

.card {
  aspect-ratio: 1 / 1;
  position: relative;
  perspective: 1000px;
}

Why aspect-ratio: 1 / 1?

  • Forces a perfect square

  • Cube math only works correctly on equal width & height

Why position: relative?

  • Anchors absolutely positioned faces

  • Prevents faces from escaping the card

Why perspective?

  • Enables real 3D depth

  • Controls how dramatic the rotation looks

Without perspective → everything looks flat.


4. Cube Depth Variable

.card {
  --depth: 150px;
}

This represents half the cube thickness.

All faces will be positioned using this value.


5. The Rotating Cube (card-inner)

.card-inner {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  transform: translateZ(calc(var(--depth) * -1));
  transition: transform 0.6s ease;
}

Line-by-line purpose:

transform-style: preserve-3d

  • Prevents browser from flattening child elements

  • Allows faces to exist on Z-axis

Without it → no cube, no depth.

translateZ(-depth)

  • Pulls the entire cube backward

  • Balances faces that are pushed forward

This centers the cube in 3D space.


6. Front Face (Image Side)

.card-front {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  transform: translateZ(var(--depth));
}

What each line does:

  • position: absolute → allows stacking

  • inset: 0 → fills the card perfectly

  • backface-visibility: hidden → hides mirrored backside

  • translateZ(depth) → pushes face to the front of cube

This is what the user sees initially.


7. Side Face (Text Side)

.card-side {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  transform: rotateY(90deg) translateZ(var(--depth));
}

Key idea:

This face starts turned sideways, so it is invisible.

  • rotateY(90deg) → faces sideways

  • translateZ(depth) → places it on cube edge

This is NOT the back — it is the side of the cube.


8. Hover Rotation

.card:hover .card-inner {
  transform: translateZ(calc(var(--depth) * -1)) rotateY(-90deg);
}

What happens on hover:

  1. Cube rotates left

  2. Front face moves out of view

  3. Side face rotates into view

  4. Feels like a real cube turn

Why 90deg and not 180deg?

  • 180deg = flip card

  • 90deg = cube rotation


9. Why backface-visibility Is Mandatory

Without it:

  • Text appears mirrored

  • Faces overlap visually

  • Rotation looks broken

With it:

  • Only faces pointing toward the viewer are rendered

10. Common Mistakes (and Why They Break)

MistakeResult
No perspectiveFlat animation
No preserve-3dFaces collapse
No translateZ(-depth)Off-center rotation
Using 180degWrong animation
No aspect-ratioDistorted cube

11. One-Paragraph Explanation (Interview / Blog)

I create a 3D cube effect by placing two faces in 3D space using translateZ and rotateY, preserving depth with transform-style: preserve-3d, and rotating the inner wrapper by 90 degrees on hover. The parent element provides perspective, while the cube is centered using a negative Z translation to maintain correct rotation geometry.


12. Final Takeaway

3D CSS is about balance:

  • Faces go forward

  • Cube goes backward

  • Camera stays outside

When all three are correct → the illusion works.