CSS 3D Transforms
In this page:
selector {
transform: rotateX(angle) rotateY(angle) translateZ(length);
perspective: length;
}
From 2D to 3D: rotateX/Y/Z
rotateX() and rotateY() tilt an element around its horizontal or vertical axis, making it appear to fold away from or toward the viewer, while rotateZ() behaves just like the familiar 2D rotate(). All three require the parent to establish a perspective for the depth effect to actually render.
- Accepted values:
- rotateX(angle) | rotateY(angle) | rotateZ(angle) — rotation around an axis
- translate3d(x, y, z) — moves in 3D
- scale3d(x, y, z) — scales in 3D
- perspective(length) — depth for one element
- perspective — length on the parent, e.g. 800px
- transform-style — flat | preserve-3d
- backface-visibility — visible | hidden
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: From 2D to 3D: rotateX/Y/Z
<style>
.scene {
perspective: 400px;
background: #eee;
padding: 30px;
}
.box {
background: steelblue;
color: white;
padding: 20px;
display: inline-block;
}
.box:hover {
transform: rotateY(45deg);
}
</style>
<div class="scene">
<div class="box">Tilted away from the viewer</div>
</div>
The perspective Property
perspective sets how far the viewer's eye is from the screen: a small value (like 200px) creates a dramatic, exaggerated 3D effect, while a large value (like 1500px) creates a subtle one. Without perspective set on a parent, 3D rotations render as if viewed from infinitely far away and look flat.
perspective-origin shifts the vanishing point itself away from the element's center, changing which side of the 3D scene appears to recede fastest.
- Accepted values:
- perspective: none — default, no perspective
- perspective: <length> — distance to the viewer, e.g. 600px
- perspective(<length>) — the same, as a transform function
- perspective-origin: <position> — vanishing point (default 50% 50%)
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: The perspective Property
<style>
.dramatic {
perspective: 200px;
background: #eee;
padding: 30px;
display: inline-block;
}
.subtle {
perspective: 1500px;
background: #eee;
padding: 30px;
display: inline-block;
}
.box {
background: steelblue;
color: white;
padding: 20px;
}
.box:hover {
transform: rotateY(45deg);
}
</style>
<div class="dramatic"><div class="box">Dramatic depth</div></div>
<div class="subtle"><div class="box">Subtle depth</div></div>
translate3d and translateZ
translate3d(x, y, z) moves an element in three dimensions at once, where a positive z value pushes it toward the viewer and a negative value pushes it away — combined with perspective, this changes the element's apparent size, just like real depth would.
- Accepted values:
- translate3d(x, y, z) — move in three dimensions
- translateZ(<length>) — move toward or away from the viewer
- scale3d(x, y, z) — scale on three axes
- rotate3d(x, y, z, angle) — rotate around a custom axis
Example: translate3d and translateZ
<style>
.scene {
perspective: 500px;
}
.box:hover {
transform: translate3d(0, 0, 100px);
}
</style>
<div class="scene">
<div class="box">Pushed toward the viewer, appears larger</div>
</div>
transform-style: preserve-3d
By default, a 3D-transformed element flattens its children into its own 2D plane. Setting transform-style: preserve-3d on the parent instead lets children keep their own independent 3D positions and rotations, which is essential for building layered 3D scenes like a rotating cube.
backface-visibility: hidden hides an element entirely once it has rotated past 90 degrees and is facing away from the viewer, which is essential for building a convincing flip-card effect where you do not want the mirrored backside text showing through.
- Accepted values:
- transform-style: flat — default, children are flattened into the parent's plane
- transform-style: preserve-3d — children keep their own 3D position
- backface-visibility: visible — default
- backface-visibility: hidden — hides the back face when rotated away
- inherit | initial | unset | revert — CSS-wide keywords accepted by every property
Example: transform-style: preserve-3d
<style>
.cube {
transform-style: preserve-3d;
}
.face {
backface-visibility: hidden;
}
</style>
<div class="cube">
<div class="face">Front face</div>
<div class="face">Back face, hidden once rotated away</div>
</div>
2D vs 3D Transforms
Unlike 2D transforms, which only reposition an element within the flat page plane, 3D transforms require a perspective context and the extra Z-axis functions (rotateX/Y, translateZ, matrix3d) to actually appear as depth rather than just a differently-shaped flat shadow.
- Accepted values:
- transform: translate() rotate() scale() skew() — 2D functions
- transform: rotateX() rotateY() translateZ() — 3D functions
- perspective — required for the depth effect to appear
- transform-style: preserve-3d — keeps nested 3D
Example: 2D vs 3D Transforms
<style>
.scene {
perspective: 400px;
}
.flat:hover {
transform: rotate(45deg);
}
.depth:hover {
transform: rotateY(45deg);
}
</style>
<div class="flat">2D: stays flat</div>
<div class="scene"><div class="depth">3D: appears to have depth</div></div>
- Forgetting
perspective, sorotateYlooks flat. - Forgetting
transform-style: preserve-3don the parent, so children are flattened. - Putting
perspectiveon the same element as the transform and not on the parent.
Supported in all modern browsers: Chrome, Firefox, Safari, Edge and Opera.
Chapter Quiz — Complete all 22 topics to unlock
0/22 topics done
Complete these topics first:
- CSS Gradients
- CSS Shadows
- CSS Filters
- CSS Blend Modes
- CSS Transforms
- CSS 2D Transforms
- CSS 3D Transforms
- CSS Transitions
- CSS Animations
- CSS Image Styling
- CSS Image Effects
- CSS Hover Overlays
- CSS Image Modal
- CSS Image Centering
- CSS Image Shapes
- CSS Buttons
- CSS Columns
- CSS Clip Path
- CSS Shapes
- CSS Scroll Snap
- CSS Architecture: BEM
- CSS Custom Properties