Home / Blog / CSS Transform: translate, rotate, scale, skew & 3D Transforms
CSS Animations 2026-09-23 · 12 min read

CSS Transform: translate, rotate, scale, skew & 3D Transforms

Master all CSS transform functions — 2D and 3D. Learn translate, rotate, scale, skew, matrix, perspective, and how transforms affect layout.

What Is CSS transform?

The transform property lets you visually move, rotate, resize, and distort elements — all without affecting the document flow. A transformed element still occupies its original space in the layout; only its rendered position changes. This makes transform ideal for animations because it never triggers a layout recalculation.

Transforms are applied in the order they are listed (right-to-left in the matrix math), which matters when combining multiple functions. transform: translateX(50px) rotate(45deg) produces a different result than rotate(45deg) translateX(50px).

2D Transform Functions

translate(), translateX(), translateY()

Moves an element along the X and/or Y axis. Values can be lengths (px, em, rem) or percentages (relative to the element's own size):

/* Move 50px right, 20px down */
.box { transform: translate(50px, 20px); }

/* Move only horizontally */
.box { transform: translateX(100px); }

/* Move only vertically */
.box { transform: translateY(-30px); }

/* Percentage: move element by 50% of its own width */
.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* Classic centering trick */
}

rotate()

Rotates an element clockwise by the specified angle. Negative values rotate counter-clockwise:

/* Rotate 45 degrees clockwise */
.icon { transform: rotate(45deg); }

/* Counter-clockwise rotation */
.icon { transform: rotate(-90deg); }

/* Fractional turns (1turn = 360deg) */
.icon { transform: rotate(0.25turn); }

/* Using radians */
.icon { transform: rotate(1.5708rad); /* π/2 = 90deg */

scale(), scaleX(), scaleY()

Resizes an element relative to its transform-origin. A value of 1 is original size; 2 is double; 0.5 is half. Negative values flip the element:

/* Scale up uniformly */
.card:hover { transform: scale(1.05); }

/* Scale horizontally only */
.progress { transform: scaleX(0.6); }

/* Flip horizontally */
.mirror { transform: scaleX(-1); }

/* Flip vertically */
.flip { transform: scaleY(-1); }

skew(), skewX(), skewY()

Tilts an element along the X and/or Y axis, creating a parallelogram effect:

/* Skew 20 degrees along X axis */
.badge { transform: skewX(-20deg); }

/* Skew both axes */
.shape { transform: skew(10deg, 5deg); }

matrix()

The matrix() function combines all 2D transforms into a single 6-value matrix. It's rarely written by hand but is what the browser uses internally:

/* matrix(scaleX, skewY, skewX, scaleY, translateX, translateY) */
.box {
  transform: matrix(1, 0.2, 0, 1, 50, 30);
  /* Equivalent to: skewY(0.2) + translateX(50px) + translateY(30px) */
}

transform-origin: Changing the Pivot Point

By default, transforms originate from the element's center (50% 50%). transform-origin changes this pivot point:

/* Rotate from top-left corner */
.fold { transform-origin: top left; transform: rotate(-5deg); }

/* Scale from bottom */
.grow { transform-origin: bottom center; transform: scale(1.2); }

/* Numeric values */
.box { transform-origin: 20px 80%; }

3D Transform Functions

CSS 3D transforms add depth along the Z-axis. To see 3D effects, you must set perspective on the parent container.

Setting Up Perspective

/* Apply perspective to the parent (scene container) */
.scene {
  perspective: 800px;        /* Smaller value = more dramatic 3D */
  perspective-origin: 50% 50%;
}

/* Or use the perspective() function inline on the element */
.box {
  transform: perspective(600px) rotateY(45deg);
}

rotateX(), rotateY(), rotateZ()

/* Flip card effect — rotate around Y axis */
.card-front { transform: rotateY(0deg); }
.card-back  { transform: rotateY(180deg); }

/* Tilt forward/backward */
.board { transform: rotateX(20deg); }

translate3d() and translateZ()

/* Move along Z axis (toward/away from viewer) */
.popup { transform: translate3d(0, 0, 50px); }

/* Equivalent to translateZ */
.popup { transform: translateZ(50px); }

scale3d() and scaleZ()

/* Scale along all three axes */
.cube-face { transform: scale3d(1, 1, 0.5); }

matrix3d()

A 4×4 matrix covering all 3D transformations. Its 16 values make it impractical to write by hand — use it when receiving matrix data from WebGL or animation libraries.

transform-style: preserve-3d

When building nested 3D elements (like a cube), child elements must inherit the 3D space. Set transform-style: preserve-3d on the parent:

.cube {
  transform-style: preserve-3d;
  animation: rotateCube 4s linear infinite;
}

@keyframes rotateCube {
  from { transform: rotateY(0deg) rotateX(0deg); }
  to   { transform: rotateY(360deg) rotateX(360deg); }
}

.face {
  position: absolute;
  width: 100px;
  height: 100px;
}

.front  { transform: translateZ(50px); }
.back   { transform: rotateY(180deg) translateZ(50px); }
.left   { transform: rotateY(-90deg) translateZ(50px); }
.right  { transform: rotateY(90deg)  translateZ(50px); }
.top    { transform: rotateX(90deg)  translateZ(50px); }
.bottom { transform: rotateX(-90deg) translateZ(50px); }

Practical Transform Patterns

Perfect Centering with translate

.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* Works regardless of modal width/height */
}

Flip Card with rotateY

.card-container {
  perspective: 1000px;
}

.card {
  width: 200px;
  height: 300px;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.6s ease;
}

.card:hover {
  transform: rotateY(180deg);
}

.card-front,
.card-back {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
}

.card-back {
  transform: rotateY(180deg);
}

Hover Scale with transform-origin

.nav-link {
  display: inline-block;
  transition: transform 0.15s ease;
  transform-origin: center bottom;
}

.nav-link:hover {
  transform: scale(1.1);
}

How transform Affects Layout

A critical point: transforms do not affect layout. Other elements in the document are completely unaware of a transformed element's visual position. A translateX(200px) moves the element visually but its original space is preserved in the flow. This is why transform is the preferred method for animation — no other elements shift or reflow when it changes.

This also means overlapping is possible. Plan your z-index accordingly when elements might overlap due to transforms.

Individual Transform Properties (Modern CSS)

Modern CSS allows you to specify transform components as separate properties instead of in one transform declaration. This is a game-changer for animations:

/* Old way — animating two transforms requires a single keyframe */
@keyframes old {
  from { transform: translateY(20px) scale(0.9); }
  to   { transform: translateY(0)    scale(1); }
}

/* New way — animate each property independently */
.element {
  translate: 0 20px;
  scale: 0.9;
  transition: translate 0.3s ease, scale 0.3s ease 0.1s;
}

.element:hover {
  translate: 0 0;
  scale: 1;
}

Individual transform properties (translate, rotate, scale) have full browser support in modern browsers and make it much easier to combine transforms in animations independently.

Experiment with all transform functions using our Live HTML/CSS/JS Editor — paste any of the examples above and see instant results.

Frequently Asked Questions

Does CSS transform affect the document flow?
No. Transforms are purely visual — the element still occupies its original space in the layout. Other elements are positioned as if the transform never happened. This is one of the key reasons transforms are preferred for animation: they cause no reflow of surrounding content.
Why does the order of transform functions matter?
Transform functions are applied in sequence (mathematically, right to left). translateX(50px) rotate(45deg) first moves the element 50px right in its original orientation, then rotates it. rotate(45deg) translateX(50px) rotates the coordinate space first, so the 50px translation goes in the rotated direction — a completely different result.
How do I center an element with unknown dimensions using transform?
Use position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);. The percentage values in translate() are relative to the element's own dimensions, so -50% moves it exactly half its own width and height back, perfectly centering it within its containing block.
What is perspective in CSS 3D transforms?
Perspective controls the "depth" of the 3D scene — how strong the foreshortening effect is. A small value (e.g., 200px) creates a dramatic, fisheye-like 3D effect. A large value (e.g., 2000px) creates subtle depth. Set perspective on the parent container, not the element being transformed.
What is backface-visibility and when do I need it?
backface-visibility: hidden hides an element when its back face is rotated toward the viewer (i.e., rotated more than 90 degrees). It's essential for flip-card effects — without it, you'd see the back card through the front card when it flips.

Try Our Free HTML CSS Tools

Practice what you've learned with our free online tools — no installation required.

Live HTML/CSS Editor CSS Formatter CSS Minifier