transform-style
Setting how children of an element are rendered in the 3D space.
Overview
| Class | Declarations |
|---|---|
transform-style:flat | transform-style: flat;
|
transform-style:preserve-3d | transform-style: preserve-3d;
|
transform-style:<value> | transform-style: <value>;
|
Examples
Preserve 3D children
Both parents rotate 32 degrees around Y and contain a child translated 48px toward the viewer. Compare flattening that child into the parent plane with preserving its depth.
<!-- Flat · child flattened into parent --><div class="grid place-items:center h:200px w:240px max-w:100% perspective:400px"> <div id="target" class="rel h:104px w:144px b:2px|solid|var(--color-violet-60) font-sm bg-violet-10 fg-violet-80 transform:rotateY(32deg) transform-style:flat"> <span class="block p-xs">Parent · 0</span> <div id="front" class="abs left-md top-xl grid place-items:center h:80px w:120px b:2px|solid|var(--color-blue-60) bg-blue-20 fg-blue-80 transform:translateZ(48px)"> Front · +48px </div> </div></div><!-- Preserve 3D · child keeps its depth --><div class="grid place-items:center h:200px w:240px max-w:100% perspective:400px"> <div id="target" class="rel h:104px w:144px b:2px|solid|var(--color-violet-60) font-sm bg-violet-10 fg-violet-80 transform:rotateY(32deg) transform-style:preserve-3d"> <span class="block p-xs">Parent · 0</span> <div id="front" class="abs left-md top-xl grid place-items:center h:80px w:120px b:2px|solid|var(--color-blue-60) bg-blue-20 fg-blue-80 transform:translateZ(48px)"> Front · +48px </div> </div></div>Generated CSS
@layer utilities { .transform-style\:preserve-3d { transform-style: preserve-3d }}The outer container supplies perspective. Transform-style controls how descendants participate in the 3D context; it does not add depth by itself. The front child’s translateZ supplies the actual displacement.
Flatten nested transforms
An explicit flat value flattens descendants. Grouping effects can also force flattening even when the computed transform-style still says preserve-3d.
<!-- Explicit flat · default flattening --><div class="grid place-items:center h:200px w:240px max-w:100% perspective:400px"> <div id="target" class="rel h:104px w:144px b:2px|solid|var(--color-violet-60) font-sm bg-violet-10 fg-violet-80 transform:rotateY(32deg) transform-style:flat"> <span class="block p-xs">Parent · 0</span> <div id="front" class="abs left-md top-xl grid place-items:center h:80px w:120px b:2px|solid|var(--color-blue-60) bg-blue-20 fg-blue-80 transform:translateZ(48px)"> Front · +48px </div> </div></div><!-- Opacity .8 · preserve-3d is flattened --><div class="grid place-items:center h:200px w:240px max-w:100% perspective:400px"> <div id="target" class="rel h:104px w:144px b:2px|solid|var(--color-violet-60) font-sm bg-violet-10 fg-violet-80 opacity:.8 transform:rotateY(32deg) transform-style:preserve-3d"> <span class="block p-xs">Parent · 0</span> <div id="front" class="abs left-md top-xl grid place-items:center h:80px w:120px b:2px|solid|var(--color-blue-60) bg-blue-20 fg-blue-80 transform:translateZ(48px)"> Front · +48px </div> </div></div>Opacity below 1 needs a flattened representation of the group. Filters, masks, isolation and some overflow values can have the same consequence. Compare the front layer’s position as well as the computed keyword; a readout alone cannot prove that depth is preserved.
Combine with perspective
Preserving depth and projecting it are separate choices. Compare the same tilted parent and front layer without perspective and with a 400px viewing distance.
<!-- No perspective · parallel projection --><div class="grid place-items:center h:200px w:240px max-w:100% perspective:none"> <div id="target" class="rel h:104px w:144px b:2px|solid|var(--color-violet-60) font-sm bg-violet-10 fg-violet-80 transform:rotateY(32deg) transform-style:preserve-3d"> <span class="block p-xs">Parent · 0</span> <div id="front" class="abs left-md top-xl grid place-items:center h:80px w:120px b:2px|solid|var(--color-blue-60) bg-blue-20 fg-blue-80 transform:translateZ(48px)"> Front · +48px </div> </div></div><!-- Perspective 400px · depth affects size --><div class="grid place-items:center h:200px w:240px max-w:100% perspective:400px"> <div id="target" class="rel h:104px w:144px b:2px|solid|var(--color-violet-60) font-sm bg-violet-10 fg-violet-80 transform:rotateY(32deg) transform-style:preserve-3d"> <span class="block p-xs">Parent · 0</span> <div id="front" class="abs left-md top-xl grid place-items:center h:80px w:120px b:2px|solid|var(--color-blue-60) bg-blue-20 fg-blue-80 transform:translateZ(48px)"> Front · +48px </div> </div></div>The perspective property on the outer container projects its children. A perspective() function instead belongs to that element’s own transform list. Keep every intermediate 3D grouping element configured deliberately; transform-style is not inherited.
Apply conditionally
Widen the viewport to sm to preserve the child’s depth. Print flattens the child into the parent plane while retaining the authored rotation.
<!-- Flat → preserve 3D at sm --><div class="grid place-items:center h:200px w:240px max-w:100% perspective:400px"> <div id="target" class="rel h:104px w:144px b:2px|solid|var(--color-violet-60) font-sm bg-violet-10 fg-violet-80 transform:rotateY(32deg) transform-style:flat transform-style:flat@print transform-style:preserve-3d@screen@sm"> <span class="block p-xs">Parent · 0</span> <div id="front" class="abs left-md top-xl grid place-items:center h:80px w:120px b:2px|solid|var(--color-blue-60) bg-blue-20 fg-blue-80 transform:translateZ(48px)"> Front · +48px </div> </div></div>Only the parent’s transform-style changes. The child’s translateZ and the outer perspective remain present in every state, exposing the native flattening difference.