3D depth with CSS

Flip and orbit in CSS with perspective and preserve-3d.

Emil Kowalskiemil-design-eng skill
rotateX(), rotateY() with transform-style: preserve-3d create real 3D effects in CSS. Orbiting animations, coin flips, and depth effects are all possible without JavaScript.
3D transforms for depthDemo 1 ↓Demo 3 ↓View source ↗

From emil-design-eng, “3D transforms for depth”.

Card flip: flat vs preserve-3d

Flip both. The flat card never shows its front.

FlatBad
no perspective · transform-style: flatback, mirrored
preserve-3dGood
perspective: 800px · preserve-3dfront
.scene { perspective: 800px; }
.card {
  transform-style: preserve-3d;
  transition: transform 300ms var(--ease-in-out);
}
.face { position: absolute; inset: 0; backface-visibility: hidden; }
.back { transform: rotateY(180deg); }
.scene[aria-pressed="true"] .card { transform: rotateY(180deg); }

Three properties, one flip

Drag the angle, then switch each property off.

Your card3D
FrontFront face
BackHello from the back
0°: front
Controls

Orbit with perspective

Tilt the orbit and pull the camera in.

FlatBad
transform-style: flat
preserve-3dGood
perspective · preserve-3d
.space { perspective: 400px; }
.system {
  transform-style: preserve-3d;
  transform: rotateX(20deg);
}
.moon { animation: orbit 4s linear infinite; }

@keyframes orbit {
  from { transform: translate(-50%, -50%) rotateY(0deg) translateZ(72px) rotateY(360deg); }
  to   { transform: translate(-50%, -50%) rotateY(360deg) translateZ(72px) rotateY(0deg); }
}

Why it matters, pros and cons

Why it matters

perspective sets the camera; preserve-3d keeps children in one 3D space.

Pros

  • Composited: no layout or paint per frame.
  • Depth sorting for free, no z-index juggling.
  • No library and no rAF loop.

Cons

  • overflow, opacity or filter silently flatten it.
  • Perspective under 400px distorts badly.
  • A flourish; skip it on UI used all day.