Difficulty: Intermediate
CSS transforms allow you to modify the visual rendering of an element by translating (moving), rotating, scaling, or skewing it in 2D or 3D space. Transforms do not affect the document flow - the element's original position in the layout is preserved, and surrounding elements are not displaced. This makes transforms ideal for animations and visual effects because they are handled by the GPU compositor, avoiding expensive layout recalculations.
The translate() function moves an element from its current position. translate(x, y) accepts length values or percentages (where 100% equals the element's own width or height). Individual axis functions translateX() and translateY() move along a single axis. A common pattern is using translate(-50%, -50%) combined with position: absolute, top: 50%, left: 50% to perfectly center an element. For 3D effects, translateZ() moves the element along the depth axis (toward or away from the viewer) and requires a perspective value on the parent.
The rotate() function spins an element around a fixed point. It accepts angle values in degrees (deg), radians (rad), gradians (grad), or turns (turn). Positive values rotate clockwise; negative values rotate counter-clockwise. For 3D rotation, rotateX() tilts forward/backward, rotateY() tilts left/right, and rotateZ() is equivalent to the 2D rotate(). The rotate3d(x, y, z, angle) function rotates around an arbitrary axis defined by a vector.
The scale() function resizes an element. scale(1) is the original size, scale(1.5) is 150%, and scale(0.5) is 50%. It accepts one value (uniform scaling) or two values (x-axis and y-axis independently). Negative scale values mirror the element: scaleX(-1) creates a horizontal flip. Scaling does not change the element's computed dimensions in the layout - a scaled-up element can overflow its container without affecting siblings.
The transform-origin property defines the point around which transforms are applied. The default is center center (50% 50%), meaning transforms radiate from the element's center. You can set it to any combination of keywords (top, right, bottom, left, center), percentages, or length values. For example, transform-origin: top left makes rotation pivot from the top-left corner, and transform-origin: 0 100% pivots from the bottom-left. For 3D transforms, a third value sets the z-axis origin. Multiple transforms can be chained in a single transform property - they are applied right to left, so the order matters.
/* Basic translation */
.move-right {
transform: translateX(100px);
}
.move-down {
transform: translateY(50px);
}
.move-diagonal {
transform: translate(100px, 50px);
}
/* Percentage-based (relative to element's own size) */
.shift-half {
transform: translateX(50%); /* Move right by half its own width */
}
/* Perfect centering pattern */
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* Hover slide effect */
.slide-link {
display: inline-block;
transition: transform 0.3s ease;
}
.slide-link:hover {
transform: translateX(8px);
}
translate() moves an element without affecting layout flow. Percentage values are relative to the element's own dimensions, not the parent - this is what makes the centering trick work. translateX/Y are shorthand for single-axis movement.
/* Rotation */
.rotate-45 {
transform: rotate(45deg);
}
.rotate-quarter {
transform: rotate(0.25turn); /* Same as 90deg */
}
.rotate-counter {
transform: rotate(-90deg);
}
/* Scale */
.grow {
transform: scale(1.2); /* 120% size */
}
.shrink {
transform: scale(0.8); /* 80% size */
}
.stretch-wide {
transform: scaleX(1.5); /* 150% width only */
}
.flip-horizontal {
transform: scaleX(-1); /* Mirror horizontally */
}
.flip-vertical {
transform: scaleY(-1); /* Mirror vertically */
}
/* Hover effects */
.avatar {
border-radius: 50%;
transition: transform 0.3s ease;
}
.avatar:hover {
transform: scale(1.1) rotate(5deg);
}
Rotation angles can be in deg, rad, grad, or turn. Positive values rotate clockwise. Scale values above 1 enlarge and below 1 shrink. Negative scale values create mirror effects. Multiple transforms can be combined in one declaration.
/* Default: center center */
.default-origin {
transform-origin: center center;
transform: rotate(45deg);
}
/* Rotate from top-left corner */
.top-left-origin {
transform-origin: top left;
transform: rotate(45deg);
}
/* Scale from bottom-right */
.bottom-right-origin {
transform-origin: bottom right;
transform: scale(1.5);
}
/* Practical example: Dropdown menu that grows from top */
.dropdown {
transform-origin: top center;
transform: scaleY(0);
opacity: 0;
transition: transform 0.2s ease, opacity 0.2s ease;
}
.dropdown.open {
transform: scaleY(1);
opacity: 1;
}
/* Tooltip that grows from its arrow */
.tooltip-bottom {
transform-origin: top center;
transform: scale(0.8);
opacity: 0;
transition: transform 0.15s ease, opacity 0.15s ease;
}
.trigger:hover .tooltip-bottom {
transform: scale(1);
opacity: 1;
}
transform-origin defines the pivot point for all transforms. For a dropdown, setting origin to 'top center' makes it appear to grow downward from its trigger. For tooltips, the origin should match where the arrow points to create a natural expansion effect.
/* Transforms are applied right to left */
.element {
/* First translates, then rotates, then scales */
transform: scale(1.2) rotate(45deg) translateX(100px);
}
/* Order matters! These produce different results: */
.order-a {
/* Moves 100px right, then rotates (around new position) */
transform: rotate(45deg) translateX(100px);
}
.order-b {
/* Rotates first, then moves along the rotated X axis */
transform: translateX(100px) rotate(45deg);
}
/* 3D transforms */
.perspective-container {
perspective: 800px; /* Depth for 3D effect */
}
.card-3d {
transition: transform 0.5s ease;
transform-style: preserve-3d;
}
.card-3d:hover {
transform: rotateY(15deg) rotateX(-5deg);
}
/* Card flip effect */
.flip-card {
perspective: 1000px;
}
.flip-inner {
transition: transform 0.6s ease;
transform-style: preserve-3d;
}
.flip-card:hover .flip-inner {
transform: rotateY(180deg);
}
Transforms chain right to left. rotate(45deg) translateX(100px) first moves 100px along the original X axis then rotates, while translateX(100px) rotate(45deg) first rotates then moves along the now-rotated axis. For 3D, set perspective on the parent and preserve-3d on the transformed element.
translate, rotate, scale, skew, transform-origin