Design.dev design.dev

CSS Transforms Guide

A complete reference for CSS transforms. Learn how to translate, rotate, scale, and skew elements in 2D and 3D space. Transforms are GPU-accelerated for smooth animations.

Translate

Move elements along the X, Y, or Z axis without affecting document flow.

translateX() & translateY()

/* Move horizontally */
.element {
  transform: translateX(50px);   /* Move right 50px */
  transform: translateX(-50px);  /* Move left 50px */
  transform: translateX(50%);    /* Move right 50% of element width */
}

/* Move vertically */
.element {
  transform: translateY(50px);   /* Move down 50px */
  transform: translateY(-50px);  /* Move up 50px */
  transform: translateY(50%);    /* Move down 50% of element height */
}

Hover over each box to see the transform:

Box
translateX(30px)
Box
translateY(30px)
Box
translateX(50%)

translate() Shorthand

/* Move both axes at once */
.element {
  transform: translate(50px, 30px);   /* X, Y */
  transform: translate(50px);         /* X only, Y = 0 */
  transform: translate(10%, 20%);     /* Percentage values */
}

/* Common centering pattern */
.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
Box
translate(20px, 20px)
Box
translate(-20px, -20px)

translateZ() & translate3d()

/* Move along Z axis (requires perspective) */
.element {
  transform: translateZ(50px);   /* Move toward viewer */
  transform: translateZ(-50px);  /* Move away from viewer */
}

/* 3D translate shorthand */
.element {
  transform: translate3d(50px, 30px, 20px);  /* X, Y, Z */
}

/* Hardware acceleration trick */
.element {
  transform: translateZ(0);  /* Forces GPU layer */
  /* or */
  transform: translate3d(0, 0, 0);
}

Rotate

Rotate elements around the center point (or a custom origin).

rotate()

/* Basic rotation (2D, around Z axis) */
.element {
  transform: rotate(45deg);    /* Clockwise 45 degrees */
  transform: rotate(-45deg);   /* Counter-clockwise */
  transform: rotate(0.25turn); /* Quarter turn (90deg) */
  transform: rotate(1turn);    /* Full rotation */
  transform: rotate(100grad);  /* Gradians (90deg) */
  transform: rotate(1rad);     /* Radians (~57.3deg) */
}

Hover over each box to see the transform:

Box
rotate(45deg)
Box
rotate(90deg)
Box
rotate(180deg)
Box
rotate(-45deg)
Box
rotate(360deg)

3D Rotation

/* Rotate around specific axis */
.element {
  transform: rotateX(45deg);  /* Rotate around X (horizontal) axis */
  transform: rotateY(45deg);  /* Rotate around Y (vertical) axis */
  transform: rotateZ(45deg);  /* Same as rotate() */
}

/* Rotate around custom axis */
.element {
  /* rotate3d(x, y, z, angle) - x,y,z define axis vector */
  transform: rotate3d(1, 0, 0, 45deg);  /* Same as rotateX */
  transform: rotate3d(0, 1, 0, 45deg);  /* Same as rotateY */
  transform: rotate3d(1, 1, 0, 45deg);  /* Diagonal axis */
  transform: rotate3d(1, 1, 1, 45deg);  /* 3D diagonal */
}

Hover to see 3D rotations (requires perspective):

Box
rotateX(45deg)
Box
rotateY(45deg)
Box
rotateZ(45deg)
Box
rotate3d(1,1,0,45deg)

Scale

Resize elements larger or smaller from their center point.

scale(), scaleX(), scaleY()

/* Uniform scaling */
.element {
  transform: scale(1.5);    /* 150% size */
  transform: scale(0.5);    /* 50% size */
  transform: scale(2);      /* Double size */
}

/* Non-uniform scaling */
.element {
  transform: scale(1.5, 0.5);  /* X: 150%, Y: 50% */
  transform: scaleX(1.5);      /* Width only */
  transform: scaleY(1.5);      /* Height only */
}

/* Flip/mirror */
.element {
  transform: scale(-1, 1);   /* Flip horizontally */
  transform: scale(1, -1);   /* Flip vertically */
  transform: scale(-1, -1);  /* Flip both (rotate 180) */
  transform: scaleX(-1);     /* Flip horizontally */
}

Hover over each box to see the transform:

Box
scale(1.3)
Box
scale(0.7)
Box
scaleX(1.5)
Box
scaleY(1.5)
Box
scale(-1, 1)

scale3d() & scaleZ()

/* 3D scaling */
.element {
  transform: scale3d(1.5, 1.5, 1.5);  /* X, Y, Z */
  transform: scaleZ(2);               /* Z axis only */
}

/* scaleZ only visible with 3D rotation */
.element {
  transform: scaleZ(2) rotateX(45deg);
}

Skew

Distort elements by tilting them along the X or Y axis.

skewX(), skewY(), skew()

/* Skew along X axis (horizontal tilt) */
.element {
  transform: skewX(15deg);
  transform: skewX(-15deg);
}

/* Skew along Y axis (vertical tilt) */
.element {
  transform: skewY(15deg);
  transform: skewY(-15deg);
}

/* Skew both axes */
.element {
  transform: skew(15deg, 10deg);  /* X, Y */
  transform: skew(15deg);         /* X only */
}

Hover over each box to see the transform:

Box
skewX(15deg)
Box
skewY(15deg)
Box
skew(10deg, 10deg)
Box
skewX(-15deg)

Note: There is no skewZ() function. Skew is a 2D-only transformation.

Transform Origin

Set the point around which transforms occur. Default is center (50% 50%).

Keywords & Values

/* Keyword values */
.element {
  transform-origin: center;        /* Default: 50% 50% */
  transform-origin: top;           /* 50% 0 */
  transform-origin: bottom;        /* 50% 100% */
  transform-origin: left;          /* 0 50% */
  transform-origin: right;         /* 100% 50% */
  transform-origin: top left;      /* 0 0 */
  transform-origin: top right;     /* 100% 0 */
  transform-origin: bottom left;   /* 0 100% */
  transform-origin: bottom right;  /* 100% 100% */
}

/* Percentage values */
.element {
  transform-origin: 25% 75%;
  transform-origin: 0% 0%;      /* Same as top left */
  transform-origin: 100% 100%;  /* Same as bottom right */
}

/* Length values */
.element {
  transform-origin: 20px 30px;
  transform-origin: 2rem 3rem;
}

/* 3D origin (X, Y, Z) */
.element {
  transform-origin: center center 50px;
  transform-origin: 50% 50% 100px;
}

Hover to see rotation from different origins:

Box
center (default)
Box
top left
Box
top right
Box
bottom left
Box
bottom right
Box
25% 75%

Combining Transforms

Apply multiple transforms in a single declaration. Order matters!

Multiple Transform Functions

/* Space-separated list of transforms */
.element {
  transform: translateX(50px) rotate(45deg);
  transform: scale(1.2) rotate(45deg) translateY(20px);
  transform: rotate(45deg) scale(1.5) skewX(10deg);
}

/* Order matters! These produce different results: */
.element-a {
  transform: translateX(100px) rotate(45deg);
  /* First move right, then rotate in place */
}

.element-b {
  transform: rotate(45deg) translateX(100px);
  /* First rotate, then move along rotated X axis */
}

Hover to see combined transforms:

Box
rotate + scale
Box
translate + rotate
Box
scale + skew

matrix() & matrix3d()

/* 2D matrix - combines all 2D transforms */
/* matrix(a, b, c, d, tx, ty) */
.element {
  /* Identity matrix (no transform) */
  transform: matrix(1, 0, 0, 1, 0, 0);
  
  /* Scale 2x horizontally */
  transform: matrix(2, 0, 0, 1, 0, 0);
  
  /* Translate 50px, 30px */
  transform: matrix(1, 0, 0, 1, 50, 30);
}

/* 3D matrix - 16 values for full 3D transformation */
/* matrix3d(a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3, a4, b4, c4, d4) */
.element {
  transform: matrix3d(
    1, 0, 0, 0,
    0, 1, 0, 0,
    0, 0, 1, 0,
    0, 0, 0, 1
  );
}

Tip: Use individual transform functions for readability. matrix() is typically generated by JavaScript libraries or browser DevTools.

3D Transforms

Create three-dimensional transformations with perspective depth.

transform-style

/* Preserve 3D transformations on children */
.parent {
  transform-style: flat;         /* Default - children flattened */
  transform-style: preserve-3d;  /* Children maintain 3D position */
}

/* Required for nested 3D transforms */
.container {
  perspective: 1000px;
}

.parent {
  transform-style: preserve-3d;
  transform: rotateY(45deg);
}

.child {
  transform: rotateX(30deg);  /* Visible in 3D space */
}

backface-visibility

/* Control visibility when rotated away */
.element {
  backface-visibility: visible;  /* Default - back is visible */
  backface-visibility: hidden;   /* Hide when facing away */
}

/* Essential for card flip effect */
.card-front,
.card-back {
  backface-visibility: hidden;
}

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

3D Card Flip Example

Front
Back
Hover to flip
.flip-container {
  perspective: 1000px;
}

.flip-card {
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.6s ease;
}

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

.flip-front,
.flip-back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
}

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

3D Cube Example

Front
Back
Right
Left
Top
Bottom
Animated 3D cube

Perspective

Add depth to 3D transforms. Lower values = more dramatic effect.

perspective Property vs Function

/* As a property (on parent) - shared vanishing point */
.parent {
  perspective: 500px;  /* Distance from viewer */
}

.parent .child {
  transform: rotateY(45deg);  /* All children share perspective */
}

/* As a function (on element) - individual perspective */
.element {
  transform: perspective(500px) rotateY(45deg);
}

/* Common values */
.element {
  perspective: 100px;   /* Very dramatic */
  perspective: 500px;   /* Moderate */
  perspective: 1000px;  /* Subtle */
  perspective: none;    /* No perspective */
}

perspective-origin

/* Set vanishing point position */
.element {
  perspective: 500px;
  perspective-origin: center;        /* Default: 50% 50% */
  perspective-origin: top;           /* Look from above */
  perspective-origin: bottom;        /* Look from below */
  perspective-origin: left;          /* Look from left */
  perspective-origin: right;         /* Look from right */
  perspective-origin: top left;      /* Look from top-left */
  perspective-origin: 25% 75%;       /* Custom position */
}

Perspective Comparison

Hover to see the same rotation with different perspectives:

Box
100px
Box
300px
Box
600px
Box
1000px

Practical Examples

Common real-world uses for CSS transforms.

Centering with Transform

/* Absolute centering */
.centered {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* Fixed modal centering */
.modal {
  position: fixed;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

Hover Effects

/* Lift on hover */
.card {
  transition: transform 0.3s ease;
}

.card:hover {
  transform: translateY(-8px);
}

/* Grow on hover */
.button {
  transition: transform 0.2s ease;
}

.button:hover {
  transform: scale(1.05);
}

/* Combined lift and grow */
.interactive {
  transition: transform 0.3s ease;
}

.interactive:hover {
  transform: translateY(-4px) scale(1.02);
}

Image Zoom in Container

.image-container {
  overflow: hidden;
}

.image-container img {
  transition: transform 0.5s ease;
}

.image-container:hover img {
  transform: scale(1.1);
}

Rotate Icon on Hover

.icon {
  transition: transform 0.3s ease;
}

.button:hover .icon {
  transform: rotate(90deg);
}

/* Full spin */
.button:hover .icon {
  transform: rotate(360deg);
}

Slide-in Animation

@keyframes slideIn {
  from {
    transform: translateX(-100%);
    opacity: 0;
  }
  to {
    transform: translateX(0);
    opacity: 1;
  }
}

.slide-in {
  animation: slideIn 0.5s ease forwards;
}

Performance Tips

Transforms are GPU-accelerated when used correctly.

GPU-Accelerated Properties

✅ Fast (Compositor)

These properties don't trigger layout or paint:

transform
opacity

⚠️ Slow (Layout/Paint)

Avoid animating these properties:

width, height
top, left
margin, padding

Best Practices

/* ❌ Bad - animates layout properties */
.element {
  left: 0;
  transition: left 0.3s;
}
.element:hover {
  left: 100px;
}

/* ✅ Good - uses transform */
.element {
  transform: translateX(0);
  transition: transform 0.3s;
}
.element:hover {
  transform: translateX(100px);
}

/* ❌ Bad - animates width */
.element {
  width: 100px;
  transition: width 0.3s;
}
.element:hover {
  width: 200px;
}

/* ✅ Good - uses scale */
.element {
  transform: scaleX(1);
  transition: transform 0.3s;
}
.element:hover {
  transform: scaleX(2);
}

will-change Hint

/* Hint browser about upcoming changes */
.element {
  will-change: transform;
}

/* Remove after animation if needed */
.element.animated {
  will-change: auto;
}

/* ❌ Don't overuse */
* {
  will-change: transform;  /* Too broad */
}

Key Rule: Use transform and opacity for animations. They run on the compositor thread without triggering expensive layout recalculations.