3D Transforms

Rotate elements in 3D space with rotateX, rotateY, rotateZ and perspective.

The Motion SDK supports 3D rotation transforms via rotateX, rotateY, and rotateZ properties. Combined with perspective, these create depth effects like card flips, tilts, and spins.

Parameters

PropertyTypeDefaultDescription
rotateXnumber0Rotation around the X axis (horizontal). Positive values tilt the top away from the viewer. In degrees.
rotateYnumber0Rotation around the Y axis (vertical). Positive values turn the left side away from the viewer. In degrees.
rotateZnumber0Rotation around the Z axis — equivalent to the 2D rotate property. In degrees.
transformOriginstring'50% 50%'Sets the pivot point for all transforms.

rotateZ and rotate are interchangeable — they produce identical results.

Perspective

3D rotations look flat without perspective. There are two ways to add it:

  • CSS on the parentperspective: 800px. All children share a single vanishing point, which looks correct when multiple elements rotate together.
  • Per-element — set perspective inline on the element itself via CSS transform: perspective(800px) rotateY(45deg), or use the SDK’s transformPerspective property. Each element has its own vanishing point.

For most SDK use cases, setting perspective in CSS on the parent container is the simplest approach:

typescript
import { Motion } from '@motion.page/sdk';

// Parent needs perspective in CSS: .scene { perspective: 800px; }
Motion('flip', '.card', {
  from: { rotateY: 180 },
  duration: 0.8,
  ease: 'power2.out',
}).play();

Axis Directions

  • rotateX — positive values tilt the top away (like leaning back in a chair); negative values tilt the top toward the viewer.
  • rotateY — positive values turn the left side away (like opening a door to the right); negative values turn the right side away.
  • rotateZ — positive values rotate clockwise; negative values rotate counter-clockwise. Identical to the 2D rotate property.

Combining Axes

You can apply multiple rotation axes simultaneously for compound 3D motion:

typescript
Motion('tilt', '.box', {
  from: { rotateX: 45, rotateY: -30 },
  duration: 1,
  ease: 'power2.out',
}).onScroll({ scrub: true });

Common Patterns

Flip in Y (card flip)

typescript
Motion('flip-y', '.card', {
  to: { rotateY: 180 },
  duration: 0.8,
  ease: 'power2.inOut',
}).onClick();

Flip in X (top-down flip)

typescript
Motion('flip-x', '.panel', {
  to: { rotateX: 180 },
  duration: 0.6,
  ease: 'power2.inOut',
}).onClick();

Perspective spin (full 360)

typescript
Motion('spin', '.logo', {
  to: { rotateY: 360 },
  duration: 1.2,
  ease: 'power1.inOut',
  repeat: -1,
}).play();

3D tilt on hover

typescript
Motion('tilt-hover', '.card', {
  to: { rotateX: -8, rotateY: 12 },
  duration: 0.4,
  ease: 'power2.out',
}).onHover({ each: true, onLeave: 'reverse' });

Scroll-driven 3D rotation

typescript
Motion('scroll-rotate', '.hero-image', {
  from: { rotateX: 25, rotateY: -15 },
  duration: 1,
}).onScroll({ scrub: true });

Tips

  • Always set perspective on the parent container in CSS. Without it, 3D rotations render flat.
  • Add transform-style: preserve-3d to the rotating element when it has 3D-transformed children (e.g. both faces of a card).
  • Use backface-visibility: hidden in CSS on card faces to hide the reverse side during a flip.
  • transformOrigin controls the pivot point — the default '50% 50%' works for most 3D rotations, but 'left center' creates a door-hinge effect.
  • Keep perspective values between 500–1200px for natural-looking depth. Lower values create more dramatic distortion; higher values make rotation more subtle.