The transform-style
property determines if the children of a transformed element are positioned in 3D space or are flattened into the 2D plane of their parent. The default value is flat
, which causes child elements to not preserve their own 3D transformations. To create nested 3D scenes, you must set transform-style: preserve-3d
on the parent container.
Example 1: Default flat
Behavior
/* style.css */
.scene {
width: 200px;
height: 200px;
perspective: 600px;
transform-style: flat; /* This is the default value */
}
.cube {
width: 100%;
height: 100%;
transform: rotateY(45deg);
}
.face {
/* The child element's 3D transform is flattened */
transform: rotateX(45deg);
}
Explanation Even though the .face
element has a rotateX
transform, it appears flattened into the same plane as its .cube
parent. This is because the parent's transform-style: flat
does not allow the child to be rendered in its own 3D space.
Example 2: Enabling 3D with preserve-3d
/* style.css */
.scene-3d {
width: 200px;
height: 200px;
perspective: 600px;
}
.cube {
width: 100%;
height: 100%;
/* This allows children to exist in a 3D space */
transform-style: preserve-3d;
transform: rotateY(45deg);
transition: transform 1s;
}
.cube:hover {
transform: rotateY(-45deg);
}
.face {
/* This child's transform is now respected */
transform: translateZ(50px);
}
Explanation By setting transform-style: preserve-3d
on the .cube
element, its child (.face
) is now positioned in a 3D context. The translateZ(50px)
on the child now correctly moves it forward in 3D space relative to its parent.
Example 3: Building a 3D Cube
/* style.css */
.container { perspective: 800px; }
.cube {
width: 150px;
height: 150px;
position: relative;
/* preserve-3d is essential for a 3D object */
transform-style: preserve-3d;
transform: rotateX(-30deg) rotateY(-30deg);
}
.face {
position: absolute;
width: 150px;
height: 150px;
opacity: 0.8;
}
.front { transform: translateZ(75px); background: red; }
.back { transform: rotateY(180deg) translateZ(75px); background: blue; }
Explanation This code creates a 3D cube by positioning multiple div
elements (.face
) in 3D space. The transform-style: preserve-3d
on the .cube
container is what makes this composition possible, ensuring each face is transformed correctly.
Example 4: Nested 3D Rotations
/* style.css */
.parent {
transform-style: preserve-3d;
transform: perspective(500px) rotateX(20deg);
}
.child {
/* This transform is relative to its parent's 3D space */
transform: rotateY(40deg);
background: #f39c12;
width: 100px;
height: 100px;
}
Explanation In this example, the .child
element's rotateY
transformation is combined with the parent's rotateX
transformation. Because the parent has transform-style: preserve-3d
, the child rotates within the already-tilted 3D plane created by the parent.
Example 5: transform-style
on a Card Flip
/* style.css */
.card-container { perspective: 1000px; }
.card {
width: 150px; height: 200px;
position: relative;
/* Allows front and back faces to share the same 3D space */
transform-style: preserve-3d;
transition: transform 0.8s;
}
.card:hover { transform: rotateY(180deg); }
.card-face { position: absolute; width: 100%; height: 100%; }
.front { background: #3498db; }
.back { background: #e74c3c; transform: rotateY(180deg); }
Explanation The transform-style: preserve-3d
on the .card
element is essential for the classic card-flip effect. It ensures that the .front
and .back
faces are positioned correctly in the same 3D space, allowing one to be revealed when the parent is rotated.
Example 6: Comparing flat
and preserve-3d
Side-by-Side
/* style.css */
.wrapper { display: flex; }
.box-container {
width: 150px;
height: 150px;
perspective: 500px;
margin: 20px;
transform: rotateY(30deg);
}
.flat { transform-style: flat; }
.preserve { transform-style: preserve-3d; }
.inner-box {
width: 100px;
height: 100px;
background: #27ae60;
/* Apply a transform to the child */
transform: rotateX(45deg);
}
Explanation This example visually demonstrates the difference. The child element in the .flat
container will appear skewed but flat, while the child in the .preserve
container will show its true rotateX
transformation within the 3D scene.
Example 7: Multi-level Nested 3D Elements
/* style.css */
.grandparent {
transform-style: preserve-3d;
transform: perspective(600px) rotateZ(20deg);
}
.parent {
transform-style: preserve-3d; /* Also needs preserve-3d */
transform: rotateX(30deg);
}
.child {
transform: translateZ(50px);
background: #8e44ad;
padding: 20px;
}
Explanation For multi-level nesting, every parent in the chain that should contain 3D-transformed children must have transform-style: preserve-3d
. This ensures the final .child
element's transformation is calculated correctly based on the accumulated transformations of all its ancestors.