2d & 3d transforms

[check: …]
📖 Pair this live Tailwind demo with the companion guide (.md) — this page is the rendered ground truth. ↗ Transforms are inert without motion — pair with transitions & timing (the transition-*, duration-*, ease-* utilities that animate every demo on this page).

1 · the v4 split: individual properties vs transform

In v3, every transform utility fed one transform: translate() rotate() scale() — so the order you wrote classes changed the result. v4 split this: 2D rotation/scale/translation now compile to the modern individual CSS properties (rotate:, scale:, translate:), which compose independently regardless of class order. Only 3D rotation (rotateX/Y/Z) and skew still use the transform property — CSS has no individual equivalents for those yet. The gold-check above proves exactly this split live.

familyTailwind v4 classcompiles towhich CSS property
2D rotate rotate-45 rotate: 45deg individual rotate (not transform)
2D scale scale-110 scale: 1.1 1.1 individual scale
2D translate translate-x-4 translate: 1rem 0 individual translate
skew skew-x-12 transform: matrix(...) transform (no individual skew prop)
3D rotate rotate-x-45 transform: rotateX(45deg) var(--tw-rotate-y) transform (pulls in --tw-rotate-* vars)
3D translate translate-z-12 transform: translateZ(0.75rem) transform

Practical consequence: combine rotate-45 scale-110 translate-x-4 in any order in v4 — they never overwrite each other because they target three different properties. In v3, swapping the class order changed the visual result.

2 · 3D rotation playground — rotate-x / rotate-y / rotate-z + perspective

Drag the sliders to rotate the cube on each axis and move the camera (perspective). Three ingredients stack: the .stage wrapper sets perspective (camera distance), the .cube sets transform-style: preserve-3d (= Tailwind transform-3d) so the six faces stay in 3D space, and each face is rotated/translated into position. Without perspective the cube renders flat-orthogonal; without preserve-3d it flattens.

-20°
30°
600px
FRONT
BACK
RIGHT
LEFT
TOP
BOTTOM
rotate-x-[-20] rotate-y-30 rotate-z-0 perspective-[600px]

computed transform: —

3 · perspective = camera distance (near vs distant)

perspective goes on the parent and sets the vanishing point. A small value (near / dramatic) is a close camera — strong foreshortening, big depth. A large value (distant) is a far camera — subtle, almost orthographic. Below, the same rotate-y-45 tile is shown under three perspective presets.

utilityvaluefeel
perspective-dramatic100pxextreme close-up, max warping
perspective-near300pxobvious 3D depth
perspective-normal500pxbalanced default
perspective-midrange800pxmild depth
perspective-distant1200pxnear-orthographic, subtle
perspective-[1000px]arbitraryany exact value
near

perspective-near (300px)

normal

perspective-normal (500px)

distant

perspective-distant (1200px)

Notice the near tile foreshortens hard (left edge stretches), the distant tile barely narrows. Same rotate-y-45 — only the camera moved.

4 · 3D flip card (hover) — transform-3d + backface-hidden

The classic flip card needs four pieces: a group parent with [perspective:1000px], an inner panel with transform-3d (preserve-3d) that group-hover:rotate-y-180s, and two faces that are backface-hidden (so you never see the reversed mirror of the other side). The back face is pre-rotated rotate-y-180 so it sits correctly behind the front.

<div class="group [perspective:1000px]"> <div class="relative transform-3d transition-transform duration-700 group-hover:rotate-y-180"> <div class="backface-hidden ...">FRONT</div> <div class="backface-hidden rotate-y-180 absolute inset-0 ...">BACK</div> </div> </div>
FRONT · hover me
BACK · flipped

Hover the card. backface-hidden = backface-visibility: hidden — crucial: without it, the front face's mirror bleeds through during the flip.

5 · 2D transform zoo — rotate · scale · skew · translate

Hover each tile. These all use the v4 individual properties (rotate:, scale:, translate:) — except skew, which still uses transform. Pair them with transition + duration-300 for the motion.

rotate

hover:rotate-45

scale

hover:scale-125

skew

hover:skew-x-12

translate

hover:translate-x-4

flip

hover:-scale-100

combo

rotate-12 + scale-110

intent → pattern

intentpatternwhy
spin a 2D element rotate-45 sets individual rotate: — composes with scale/translate freely
flip on hover (mirror) hover:-scale-100 negative scale flips; -scale-x-100 for horizontal only
give a 3D child real depth parent perspective-[1000px] + child rotate-x-45 perspective on PARENT; without it 3D rotation looks flat
nest 3D children transform-3d on the middle wrapper transform-style: preserve-3d — default flat squashes children
flip card transform-3d + backface-hidden + group-hover:rotate-y-180 backface-hidden prevents the mirror bleeding through
animate a transform transition-[transform,rotate,scale,translate] duration-300 v4 individual props are separate — name them all, or use transition-all
custom axis rotation rotate-x-[18deg] arbitrary value for any non-preset degree