CSS 3D transforms extend normal transforms by adding depth. Instead of only moving left, right, up, and down, elements can rotate around the X and Y axes or move closer to and farther from the viewer.
The most important property is perspective. Without perspective, 3D rotation can look flat because the browser has no viewer distance to create depth. Place perspective on the parent scene, then transform the child element inside that scene.
Treat a 3D transform as a small stage. The parent creates viewing distance with perspective, and the child preserves face depth with transform-style: preserve-3d.
| Property/Function | Description |
|---|---|
| perspective | Distance from viewer to z=0 plane - creates depth illusion |
| transform-style: preserve-3d | Children maintain their 3D position |
| backface-visibility | Show/hide back face of element |
| rotateX(angle) | Rotate around X axis (tilt forward/back) |
| rotateY(angle) | Rotate around Y axis (spin left/right) |
| rotateZ(angle) | Rotate around Z axis (same as 2D rotate) |
| translateZ(z) | Move toward/away from viewer |
| scaleZ(z) | Scale along Z axis |
/* 3D card Flip */
.flip-container {
perspective: 1000px; /* distance from viewer - creates depth */
width: 300px;
height: 200px;
}
.flip-card {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d; /* children maintain 3D position */
transition: transform 0.6s ease;
}
.flip-container:hover .flip-card {
transform: rotateY(180deg); /* flip on hover */
}
.flip-front,
.flip-back {
position: absolute;
inset: 0;
backface-visibility: hidden; /* hide when facing away */
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.2rem;
font-weight: bold;
}
.flip-front {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
}
.flip-back {
background: linear-gradient(135deg, #f093fb, #f5576c);
color: white;
transform: rotateY(180deg); /* pre-rotated - starts facing away */
}
/* 3D Cube */
.scene {
perspective: 600px;
width: 100px;
height: 100px;
}
.cube {
width: 100%;
height: 100%;
position: relative;
transform-style: preserve-3d;
animation: rotateCube 4s linear infinite;
}
.face {
position: absolute;
width: 100px;
height: 100px;
border: 2px solid rgba(255,255,255,0.3);
background: rgba(52,152,219,0.6);
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
}
.front { transform: translateZ(50px); }
.back { transform: rotateY(180deg) translateZ(50px); }
.left { transform: rotateY(-90deg) translateZ(50px); }
.right { transform: rotateY(90deg) translateZ(50px); }
.top { transform: rotateX(90deg) translateZ(50px); }
.bottom { transform: rotateX(-90deg) translateZ(50px); }
@keyframes rotateCube {
from { transform: rotateX(0) rotateY(0); }
to { transform: rotateX(360deg) rotateY(360deg); }
}
<!-- 3D card Flip -->
<div class="flip-container">
<div class="flip-card">
<div class="flip-front">Front Side</div>
<div class="flip-back">Back Side</div>
</div>
</div>
<!-- 3D Cube -->
<div class="scene">
<div class="cube">
<div class="face front">F</div>
<div class="face back">B</div>
<div class="face left">L</div>
<div class="face right">R</div>
<div class="face top">T</div>
<div class="face bottom">Bo</div>
</div>
</div>
For a flip card, each side is positioned in the same place. The back side starts rotated 180 degrees, and backface-visibility hides whichever side is facing away from the viewer. When the inner card rotates, the hidden and visible faces swap.
Use 3D effects for special interactions, not for basic layout. They can be eye-catching, but too much rotation can reduce readability and feel distracting on touch devices.
@media (prefers-reduced-motion: reduce) {
.flip-card {
transition: none;
transform: none;
}
.flip-container:hover .flip-card {
transform: none;
}
}
.lesson-box:empty::before {
content: "CSS 3D Transforms perspective rotateX rotateY: add visible content";
}
The parent likely needs perspective, or the perspective value is too large to show obvious depth.
Usually on the parent scene that contains the transformed child.
It lets child elements keep their 3D positions instead of being flattened into the parent plane.
Explore 500+ free tutorials across 20+ languages and frameworks.