CSS transform-style Property

The transform-style property determines if the children of an element are positioned in the 2D plane of the parent or can exist in 3D space.

selector { transform-style: value; }
flat Forces all child elements to be rendered flattened into the plane of the parent element.
preserve-3d Allows child elements to maintain their positions in 3D space relative to the parent.

Code Examples

This basic example shows a parent element rotated in 3D space while its child is pushed forward on the Z-axis, maintaining its 3D position.

<div style="perspective: 800px;">
  <div style="width: 200px; height: 200px; background: #333333; transform-style: preserve-3d; transform: rotateY(45deg);">
    <div style="width: 100px; height: 100px; background: #ff0000; transform: translateZ(50px);">
      I am floating in front.
    </div>
  </div>
</div>

An advanced semantic setup using JavaScript to rotate a 3D container with two faces, where "preserve-3d" ensures the faces stay separated in space.

<div id="scene" style="perspective: 1000px; width: 300px; height: 300px; margin: 50px auto;">
  <div id="cube" style="width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 1s;">
    <div style="position: absolute; width: 300px; height: 300px; background: rgba(0, 0, 255, 0.5); transform: translateZ(150px);">Front</div>
    <div style="position: absolute; width: 300px; height: 300px; background: rgba(255, 0, 0, 0.5); transform: rotateY(180deg) translateZ(150px);">Back</div>
  </div>
</div>
<button onclick="toggle3D()">Toggle Rotation</button>
<script>
  function toggle3D() {
    const cube = document.getElementById("cube");
    cube.style.transform = cube.style.transform === "rotateY(180deg)" ? "rotateY(0deg)" : "rotateY(180deg)";
  }
</script>

Pro Tip

If you are building a 3D flip card, you only need "preserve-3d" on the container that holds the front and back faces. This allows the faces to be positioned back-to-back and rotate together as a single unit without losing their spatial relationship. If you see flickering or elements clipping through each other during a rotation, double-check that your "transform-style" is set correctly on the wrapper.

Deep Dive

Think of an element like a sheet of paper. By default, anything you draw or place on that paper is flat against it. This is the "flat" value. When you switch to "preserve-3d", that sheet of paper becomes more like a transparent glass box. Now, child elements are no longer stuck to the surface; they can move forward toward the viewer or backward away from the viewer. This property creates a 3D rendering context. Without it, even if you give a child element a Z-axis translation, the browser will squash it back down onto the parent's surface, ruining the depth effect. It is important to remember that this property must be applied to the parent container, not the children you are trying to move.

Best Practices

Apply this property only to the immediate parent of the elements that require 3D positioning. If you have a deep nesting of 3D elements, you must apply "preserve-3d" to every level of the hierarchy to keep that 3D context alive down the chain. Avoid using it on every element in your DOM, as creating 3D rendering contexts requires more GPU resources and can impact the performance of your site if overused.

Common Pitfalls

The biggest trap developers fall into is setting "overflow: hidden", "clip", or "clip-path" on the parent element. Doing this will force the "transform-style" back to "flat" and kill your 3D effect instantly. Also, keep in mind that this property is not inherited by grandchildren; it only affects the immediate children of the element it is applied to. If your 3D scene looks like a flat sticker, check your parent containers for these properties.

Accessibility

When creating 3D interfaces, ensure that content remains legible and interactive. Rotating elements away from the viewer can make text difficult to read or make buttons impossible to click. Always test that screen readers can still navigate the content in a logical order, regardless of where the elements are visually floating in 3D space.

Dev Data Table: transform-style property

default flat
animatable no
inherited no
experimental no
year_intro 2011
year_standard 2015
js_syntax_1 object.style.transformStyle = "preserve-3d";
js_syntax_2 object.style.setProperty("transform-style", "preserve-3d");
js_note In JavaScript, use camelCase for the property name when accessing the style object directly.
browsers { "Chrome": 36, "Edge": 12, "Firefox": 16, "Safari": 9, "Opera": 23, "Chrome Android": 36, "Safari on iOS": 9, "Samsung Internet": 3, "Opera Mobile": 23 }
results render here...