| |

Tailwind CSS 26 🎨 Native 3D Transforms (Perspective, Transform-Style, Rotate-3D)

For most of its history, Tailwind CSS treated 3D transforms as a gap. The 2D transforms were covered by scale-*, rotate-*, translate-*, and skew-*, but anything involving the Z-axis required arbitrary values or a community plugin. Tailwind v4 closed that gap with native utilities for perspective, axis-specific rotation, Z-axis translation, and 3D rendering contexts. These utilities follow the same composable model as the 2D transforms: each one sets a value, and the transform property combines them. This chapter covers the full 3D transform stack, the parent-child relationship between perspective and rotation, and the patterns that produce effects like card flips and layered parallax.

Key point: 3D transforms in Tailwind require two things: a parent with perspective and 3D context, and a child with the 3D rotation or translation. Without a perspective value on the parent, a rotated child looks flat because the browser has no reference for depth. Without transform-3d on the parent, child transforms are flattened to 2D regardless of what rotation is applied.


Why 3D transform utilities exist

The plugin problem. Before v4, developers who needed 3D transforms reached for plugins like tailwindcss-3d or wrote arbitrary values like [transform:rotateY(45deg)]. Plugins added a dependency and a vocabulary that was not part of the core framework. Arbitrary values worked but lost the composable structure: each 3D transform was a single opaque string, and combining rotate and translate on the Z-axis required writing the full transform declaration manually.

The CSS perspective problem. 3D transforms in CSS are not just rotations around new axes. They require a perspective value on an ancestor to establish the viewing distance, and a transform-style: preserve-3d on the container to keep children in the 3D space rather than flattening them. These are easy to forget, and the failure mode is silent: the element rotates, but it looks flat. Native utilities make the requirements explicit and composable.

The composability problem. A 3D card might rotate around the X-axis, translate along the Z-axis, and scale slightly. In CSS, that is a single transform declaration with three functions in a specific order. Tailwind’s utilities set individual CSS variables—--tw-rotate-x, --tw-translate-z, --tw-scale—and the transform property references them. Adding or removing one transform does not require rewriting the others.

The consistency problem. The 3D utilities follow the same scale and naming conventions as the 2D utilities. rotate-x-45 matches the pattern of rotate-45. translate-z-4 matches the spacing scale. perspective-normal matches the descriptive naming of other utilities. Learning one family teaches the pattern for the others.

The v4-only problem. These utilities are Tailwind v4 only. They do not exist in v3.4 or earlier, and they are not available through a compatibility layer. Projects on v3 that need 3D transforms must use a plugin or arbitrary values. The migration to v4 is the prerequisite for native 3D support.


a. Perspective and transform-style

Perspective is the property that gives depth to 3D transforms. It defines the distance between the viewer and the z-plane. A smaller value creates a more dramatic effect; a larger value creates a subtler one.

<div class="perspective-dramatic">
  <div class="rotate-y-45">Content</div>
</div>

Tailwind provides named perspective utilities:

UtilityCSS ValueEffect
perspective-dramatic100pxExtreme depth
perspective-near300pxClose perspective
perspective-normal500pxDefault depth
perspective-midrange800pxModerate depth
perspective-distant1200pxSubtle depth

The perspective value is applied to the parent of the transformed element, not the element itself. Without a perspective value somewhere up the tree, a 3D rotation has no depth reference, and the element appears to squash rather than rotate in space.

Custom perspective values are defined through the theme:

@theme {
  --perspective-remote: 1800px;
}

The custom value becomes a utility: perspective-remote.

The perspective-origin-* utilities control the vanishing point—the point at which the perspective converges. This works like transform-origin but for the perspective effect.

<div class="perspective-normal perspective-origin-top-left">
  <div class="rotate-x-45">Content</div>
</div>

The origin determines where the element appears to recede toward. The default is center. Moving it to a corner changes the visual effect without changing the rotation.

Transform-style is the other parent-side requirement. By default, browsers flatten the 3D transforms of children into a 2D plane. The transform-3d utility sets transform-style: preserve-3d, which keeps children in the 3D space.

<div class="perspective-normal transform-3d">
  <div class="rotate-x-45">Child</div>
</div>

Without transform-3d on the container, a child with rotate-y-180 would appear to flip but would be flattened against the parent plane. With it, the child occupies its own 3D orientation.

The transform-flat utility sets transform-style: flat, which is the default. It is used to explicitly reset the 3D context for a subtree that should not inherit it.


b. 3D rotation and translation

The 3D rotation utilities rotate an element around a specific axis. The axis is part of the utility name.

UtilityCSSEffect
rotate-x-45rotateX(45deg)Tilt forward/backward
rotate-y-45rotateY(45deg)Turn left/right
rotate-z-45rotateZ(45deg)2D rotation (equivalent to rotate-45)

The scales for each axis follow the 2D rotate scale: 0, 1, 2, 3, 6, 12, 45, 90, 180. Negative values use a leading dash: -rotate-x-45.

<div class="rotate-x-45">Tilted forward</div>
<div class="rotate-y-90">Turned sideways</div>
<div class="rotate-z-12">Same as rotate-12</div>

The axes combine. A single element can rotate on multiple axes:

<div class="rotate-x-50 rotate-z-45">
  Complex orientation
</div>

The order of composition is fixed by Tailwind’s transform property. The functions are applied in a specific sequence, and the result is predictable across browsers.

Z-axis translation moves an element toward or away from the viewer. The translate-z-* utilities use the spacing scale, with negative values moving away.

<div class="translate-z-4">Closer to viewer</div>
<div class="-translate-z-4">Further from viewer</div>
<div class="translate-z-1/2">Half the element's size closer</div>

The Z-axis translation is what creates parallax effects: elements at different Z positions appear to move at different rates when the perspective origin shifts. Combined with perspective on the parent, it produces layered depth.

Backface visibility controls whether the back of a rotated element is visible. When an element is rotated past 90 degrees, its back faces the viewer. The backface-hidden utility hides it; backface-visible shows it.

<div class="rotate-y-180 backface-hidden">
  Hidden when facing away
</div>

This is essential for card flips. The front and back of the card are two elements, each with backface-hidden. When the card rotates 180 degrees, the front faces away and is hidden, and the back faces the viewer and is visible.


c. Building 3D patterns

The card flip is the canonical 3D pattern. It requires a parent with perspective, an inner container with transform-3d, and two children with backface-hidden.

<div class="perspective-distant group">
  <div class="relative w-64 h-96 transform-3d transition-transform duration-500 group-hover:rotate-y-180">
    <div class="absolute inset-0 backface-hidden bg-blue-500 flex items-center justify-center">
      Front
    </div>
    <div class="absolute inset-0 backface-hidden rotate-y-180 bg-red-500 flex items-center justify-center">
      Back
    </div>
  </div>
</div>

The outer div has perspective-distant, which establishes the viewing distance. The inner div has transform-3d, which preserves the 3D space for its children. The two card faces are absolutely positioned on top of each other. The front is unrotated; the back is rotated 180 degrees so that its front face points away. Both have backface-hidden. On hover, the inner container rotates 180 degrees, bringing the back into view and hiding the front.

A parallax tilt effect uses rotation on both axes, driven by mouse position or scroll:

<div class="perspective-normal">
  <div class="rotate-x-12 rotate-y-12 transition-transform">
    Tilted card
  </div>
</div>

A layered depth effect uses Z-axis translation on multiple elements within a 3D context:

<div class="perspective-normal transform-3d">
  <div class="translate-z-0">Base layer</div>
  <div class="translate-z-8">Middle layer</div>
  <div class="translate-z-16">Top layer</div>
</div>

Each layer sits at a different Z position. When the perspective origin moves, the layers appear to shift relative to each other, creating the parallax effect.

A cube uses six faces, each rotated and translated to form a cube in 3D space:

<div class="perspective-normal transform-3d">
  <div class="rotate-y-0 translate-z-16">Front</div>
  <div class="rotate-y-90 translate-z-16">Right</div>
  <div class="rotate-y-180 translate-z-16">Back</div>
  <div class="rotate-y-270 translate-z-16">Left</div>
  <div class="rotate-x-90 translate-z-16">Top</div>
  <div class="-rotate-x-90 translate-z-16">Bottom</div>
</div>

Each face is rotated to point in a direction and translated along its new Z-axis to the edge of the cube. The parent with transform-3d keeps the faces in the same 3D space.


Complete Example Session

<!-- ============================================ -->
<!-- PART 1: PERSPECTIVE ON PARENT -->
<!-- ============================================ -->
<div class="perspective-dramatic">
  <div class="rotate-y-45">Content</div>
</div>
<!-- ============================================ -->
<!-- PART 2: PERSPECTIVE SCALE -->
<!-- ============================================ -->
<div class="perspective-near">Near (300px)</div>
<div class="perspective-normal">Normal (500px)</div>
<div class="perspective-distant">Distant (1200px)</div>
<!-- ============================================ -->
<!-- PART 3: TRANSFORM-3D -->
<!-- ============================================ -->
<div class="perspective-normal transform-3d">
  <div class="rotate-x-45">Child in 3D space</div>
</div>
<!-- ============================================ -->
<!-- PART 4: AXIS-SPECIFIC ROTATION -->
<!-- ============================================ -->
<div class="rotate-x-45">Tilt forward</div>
<div class="rotate-y-45">Turn sideways</div>
<div class="rotate-z-45">2D rotation</div>
<!-- ============================================ -->
<!-- PART 5: COMBINED ROTATION -->
<!-- ============================================ -->
<div class="rotate-x-50 rotate-z-45">Complex orientation</div>
<!-- ============================================ -->
<!-- PART 6: Z-AXIS TRANSLATION -->
<!-- ============================================ -->
<div class="translate-z-8">Closer</div>
<div class="-translate-z-8">Further</div>
<!-- ============================================ -->
<!-- PART 7: BACKFACE VISIBILITY -->
<!-- ============================================ -->
<div class="rotate-y-180 backface-hidden">Hidden from back</div>
<div class="rotate-y-180 backface-visible">Visible from back</div>
<!-- ============================================ -->
<!-- PART 8: CARD FLIP -->
<!-- ============================================ -->
<div class="perspective-distant group">
  <div class="relative w-64 h-96 transform-3d transition-transform duration-500 group-hover:rotate-y-180">
    <div class="absolute inset-0 backface-hidden bg-blue-500">Front</div>
    <div class="absolute inset-0 backface-hidden rotate-y-180 bg-red-500">Back</div>
  </div>
</div>
<!-- ============================================ -->
<!-- PART 9: PARALLAX LAYERS -->
<!-- ============================================ -->
<div class="perspective-normal transform-3d">
  <div class="translate-z-0">Background</div>
  <div class="translate-z-8">Middle</div>
  <div class="translate-z-16">Foreground</div>
</div>
<!-- ============================================ -->
<!-- PART 10: CUSTOM PERSPECTIVE -->
<!-- ============================================ -->
<style>
@theme {
  --perspective-remote: 1800px;
}
</style>

<div class="perspective-remote">
  <div class="rotate-x-12">Subtle tilt</div>
</div>

The ten parts covered perspective on the parent, the perspective scale, transform-3d, axis-specific rotation, combined rotation, Z-axis translation, backface visibility, the card flip, parallax layers, and custom perspective values.


Quick Reference

Perspective Utilities

UtilityCSS Value
perspective-dramatic100px
perspective-near300px
perspective-normal500px
perspective-midrange800px
perspective-distant1200px
perspective-[...]Arbitrary value

Transform-Style Utilities

UtilityCSS
transform-3dtransform-style: preserve-3d
transform-flattransform-style: flat

3D Rotation

UtilityAxis
rotate-x-*Horizontal axis
rotate-y-*Vertical axis
rotate-z-*Depth axis (2D)

Z-Axis Translation

UtilityEffect
translate-z-*Move toward viewer
-translate-z-*Move away from viewer

Backface

UtilityCSS
backface-visiblebackface-visibility: visible
backface-hiddenbackface-visibility: hidden

Perspective Origin

UtilityVanishing Point
perspective-origin-centerCenter (default)
perspective-origin-topTop
perspective-origin-bottom-leftBottom-left
perspective-origin-*Corner and edge variants

Best Practices

✅ Do This:

<!-- Put perspective on the parent -->
<div class="perspective-normal">
  <div class="rotate-y-45">Child</div>
</div>                                                        <!-- ✅ -->

<!-- Use transform-3d on the container -->
<div class="perspective-normal transform-3d">
  <div class="rotate-x-45">Child</div>
</div>                                                        <!-- ✅ -->

<!-- Use backface-hidden for flips -->
<div class="backface-hidden rotate-y-180">Back</div>          <!-- ✅ -->

<!-- Combine axes for complex orientation -->
<div class="rotate-x-45 rotate-y-12">Card</div>               <!-- ✅ -->

<!-- Use transition-transform for smooth 3D animation -->
<div class="transition-transform hover:rotate-y-180">         <!-- ✅ -->

<!-- Define custom perspective values in the theme -->
@theme { --perspective-remote: 1800px; }                      <!-- ✅ -->

❌ Don’t Do This:

<!-- Don't put perspective on the rotated element itself -->
<div class="perspective-normal rotate-y-45">Wrong</div>       <!-- ❌ -->

<!-- Don't forget transform-3d on the container -->
<div class="perspective-normal">
  <div class="rotate-x-45">Flattened</div>
</div>                                                        <!-- ❌ -->

<!-- Don't use rotate-* expecting 3D -->
<div class="rotate-45">This is 2D rotate-z</div>              <!-- ⚠️ -->

<!-- Don't omit backface-hidden on flips -->
<div class="rotate-y-180">Both sides visible</div>            <!-- ❌ -->

<!-- Don't use v4 utilities in a v3 project -->
<div class="rotate-x-45">Not available in v3</div>            <!-- ❌ -->

<!-- Don't nest 3D contexts without resetting -->
<div class="transform-3d">
  <div class="transform-3d">Nested contexts</div>
</div>                                                        <!-- ⚠️ -->

Common Pitfalls

PitfallWhy It HappensFix
Rotation looks flatNo perspective on parentAdd perspective-* to parent
Child transforms flattenedNo transform-3d on containerAdd transform-3d
Both sides of card visibleNo backface-hiddenAdd to each face
Perspective on wrong elementApplied to the rotated childMove to parent
3D utilities not recognizedv3 projectUpgrade to v4
Z-translation has no effectNo perspective contextAdd perspective to parent
Custom perspective not workingNot defined in @themeAdd --perspective-* variable

Real-World Examples

1. Card Flip on Hover

<div class="perspective-distant group">
  <div class="relative w-64 h-96 transform-3d transition-transform duration-500 group-hover:rotate-y-180">
    <div class="absolute inset-0 backface-hidden bg-blue-500">Front</div>
    <div class="absolute inset-0 backface-hidden rotate-y-180 bg-red-500">Back</div>
  </div>
</div>

2. Tilted Card

<div class="perspective-normal">
  <div class="rotate-x-12 rotate-y-12 transition-transform">Card</div>
</div>

3. Parallax Layers

<div class="perspective-normal transform-3d">
  <div class="translate-z-0">Background</div>
  <div class="translate-z-8">Middle</div>
  <div class="translate-z-16">Foreground</div>
</div>

4. Cube Face

<div class="rotate-y-90 translate-z-16">Right face</div>

5. Flip Card Back

<div class="backface-hidden rotate-y-180">Back content</div>

6. Subtle Tilt on Hover

<div class="perspective-distant transition-transform hover:rotate-x-6">Card</div>

7. Y-Axis Rotation

<div class="rotate-y-45">Side view</div>

8. X-Axis Rotation

<div class="rotate-x-45">Top view</div>

9. Custom Perspective

<div class="perspective-remote">Distant perspective</div>

10. Perspective Origin

<div class="perspective-normal perspective-origin-top-left">
  <div class="rotate-x-45">Tilted</div>
</div>

Visual

3D Transform Stack

┌─────────────────────────────────────────────────────────────┐
│  PARENT (perspective)                                       │
│  ┌─────────────────────────────────────────────────────┐    │
│  │  perspective-normal (500px)                         │    │
│  │                                                     │    │
│  │  ┌───────────────────────────────────────────────┐  │    │
│  │  │  CONTAINER (transform-3d)                     │  │    │
│  │  │  transform-style: preserve-3d                 │  │    │
│  │  │                                               │  │    │
│  │  │  ┌─────────────────────────────────────────┐  │  │    │
│  │  │  │  CHILD (rotate-x, rotate-y, translate-z)│  │  │    │
│  │  │  │  3D transform                           │  │  │    │
│  │  │  └─────────────────────────────────────────┘  │  │    │
│  │  └───────────────────────────────────────────────┘  │    │
│  └─────────────────────────────────────────────────────┘    │
│                                                             │
│  Perspective on parent, 3D context on container,           │
│  rotation on child.                                         │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Rotation Axes

┌─────────────────────────────────────────────────────────────┐
│  rotate-x-45                                                │
│                                                             │
│      ──────────────                                         │
│     ╱              ╲    Tilt forward                        │
│    ╱                ╲   (nodding)                           │
│                                                             │
│  rotate-y-45                                                │
│                                                             │
│      │              │                                       │
│      │              │   Turn sideways                       │
│      │              │   (shaking head)                      │
│                                                             │
│  rotate-z-45                                                │
│                                                             │
│        ╱                                                    │
│       ╱            2D rotation                              │
│      ╱             (same as rotate-45)                      │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Card Flip Sequence

┌─────────────────────────────────────────────────────────────┐
│  INITIAL STATE                                              │
│                                                             │
│  Front (rotate-y-0)          Back (rotate-y-180)            │
│  ┌─────────────┐             ┌─────────────┐                │
│  │   FRONT     │             │    BACK     │                │
│  │  (facing    │             │  (facing    │                │
│  │   viewer)   │             │   away)     │                │
│  └─────────────┘             └─────────────┘                │
│                                                             │
│  Backface-hidden on both.                                   │
│  Only the front is visible.                                 │
│                                                             │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│  AFTER HOVER (rotate-y-180 on container)                    │
│                                                             │
│  Front (now rotate-y-180)    Back (now rotate-y-0)          │
│  ┌─────────────┐             ┌─────────────┐                │
│  │   FRONT     │             │    BACK     │                │
│  │  (facing    │             │  (facing    │                │
│  │   away)     │             │   viewer)   │                │
│  └─────────────┘             └─────────────┘                │
│                                                             │
│  The container rotated, bringing the back into view.        │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Perspective Scale Comparison

┌─────────────────────────────────────────────────────────────┐
│  perspective-dramatic (100px)                               │
│  ┌───────┐                                                  │
│  │      ╱│  Extreme depth                                   │
│  │    ╱  │  Rotation looks dramatic                         │
│  │  ╱    │                                                  │
│  └───────┘                                                  │
│                                                             │
│  perspective-normal (500px)                                 │
│  ┌───────┐                                                  │
│  │      ╱│  Moderate depth                                  │
│  │    ╱  │  Balanced effect                                 │
│  │  ╱    │                                                  │
│  └───────┘                                                  │
│                                                             │
│  perspective-distant (1200px)                               │
│  ┌───────┐                                                  │
│  │      ╱│  Subtle depth                                    │
│  │    ╱  │  Barely noticeable                               │
│  │  ╱    │                                                  │
│  └───────┘                                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

Summary

ItemValue
Perspectiveperspective-{dramatic,near,normal,midrange,distant}
Perspective originperspective-origin-*
3D contexttransform-3d (preserve-3d)
Flatten contexttransform-flat
X-axis rotationrotate-x-*
Y-axis rotationrotate-y-*
Z-axis rotationrotate-z-* (same as rotate-*)
Z-axis translationtranslate-z-*
Backface visiblebackface-visible
Backface hiddenbackface-hidden
Custom perspective@theme { --perspective-*: ... }
VersionTailwind v4 only

Key takeaways:

  • Perspective goes on the parent, not the rotated element. The perspective value establishes the viewing distance. Without it, a 3D rotation appears flat because the browser has no depth reference.
  • transform-3d keeps children in the 3D space. By default, browsers flatten child transforms into the parent’s 2D plane. transform-3d sets transform-style: preserve-3d, which allows children to occupy their own 3D orientations.
  • 3D rotation is axis-specific. rotate-x-* tilts around the horizontal axis, rotate-y-* turns around the vertical axis, and rotate-z-* is the 2D rotation equivalent. The axes combine for complex orientations.
  • Z-axis translation creates depth. translate-z-* moves elements toward or away from the viewer. Combined with perspective, it produces parallax effects where layers move at different rates.
  • backface-hidden is essential for card flips. Without it, the reverse side of a rotated element shows through. With it, the element disappears when its back faces the viewer.
  • These utilities are v4 only. They do not exist in Tailwind v3.4 or earlier. Projects that need 3D transforms on v3 must use a plugin or arbitrary values.
  • Custom perspective values are defined in the theme. @theme { --perspective-remote: 1800px; } creates a perspective-remote utility that matches the design system.

Remember: 3D transforms in Tailwind v4 follow the same composable model as the 2D transforms. Perspective on the parent establishes depth. transform-3d on the container preserves the 3D space. Rotation and translation on the child position the element. Backface visibility controls what shows when the element turns away. The card flip is the canonical pattern: a parent with perspective, a container with transform-3d, and two faces with backface-hidden, one rotated 180 degrees. The same pieces build parallax layers, tilted cards, and cubes. The utilities are new in v4, and they close a gap that previously required plugins or arbitrary values. Learn the parent-child relationship, and the rest of the 3D system follows.



Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!