CSS Transform Functions Table

FunctionWhat it doesField note
translate(x, y)Move from its spotPercentages refer to the ELEMENT's own size - not the parent
rotate(deg)Spin around the origintransform-origin decides the pivot - default is center
scale(sx, sy)Resize visuallyLayout is untouched - text stays crisp, unlike zooming a bitmap
skew(x, y)Slant the axesPure display distortion - rare outside decorative shapes
matrix()All six values at onceWhat the browser reduces transforms to - readable in devtools
translateZ / 3dPerspective gamesNeeds perspective on the parent to show depth
transform-originThe pivot pointrotate(45deg) around top-left vs center are different layouts
chained transformstranslate() rotate() scale()Order matters - translate-then-rotate differs from rotate-then-translate
Reference: the MDN transform reference. Transforms move the PAINTED result, not the layout: a translated or scaled element keeps its original box - neighbors never reflow, text stays vector-crisp, and animation runs on the compositor. That is the whole performance story: animating transform is GPU-cheap, animating top/left is layout thrash. Bottom line: transform-origin picks the pivot (the default center surprises nobody once named), percentages in translate refer to the element itself, and chain order matters - translate(100px) rotate(45deg) lands the rotation elsewhere than the reverse order. Related tools: animations table (transform is the animation-friendly property), box-shadow table (transforms create containing blocks - fixed children re-anchor), and filter table (the other compositor-friendly layer).

Transforms move the PAINTED result, not the layout: a translated, rotated or scaled element keeps its original box in the flow - neighbors never reflow, text stays vector-crisp, and the browser composites the change on the GPU. That is the entire performance story of modern animation.

Bottom line: animating transform is GPU-cheap while animating top/left is layout thrash - same visual motion, opposite cost. The model has two knobs people miss: transform-origin picks the pivot (rotate around center vs top-left are different layouts), and percentages in translate refer to the ELEMENT's own size, not the parent's.

The honest part: transforms chain, and chains are order-sensitive math - translate(100px) rotate(45deg) lands the rotation in a different place than rotate(45deg) translate(100px). Read the chain left to right as instructions applied to the element's local coordinate system, and the divergence stops being mysterious.

How to use

  1. Center anything absolutely-positioned: left: 50%; top: 50%; transform: translate(-50%, -50%) - the percentages measuring the element itself is what makes it size-independent.
  2. Animate only transform and opacity: hover lifts become translate(0, -4px), entrances become translateY + opacity - compositor work, no layout, no jank.
  3. Set the pivot deliberately: transform-origin: bottom center makes a card lift like a hinge from its base - the default center is one choice, not the law.

Frequently asked questions

Why does transform: translate() beat position tweaks for animation?

Layout versus paint. Changing top/left invalidates layout: the engine recomputes geometry for the element and potentially everything after it, every frame - 60 of those per second is the classic jank. Transform happens after layout, on the composited layer: the element's box never moves, so no reflow is triggered, and the GPU slides the already-painted texture. The exception worth knowing: transform creates a containing block, so fixed-position children re-anchor to the transformed element - the same gotcha as filter.

What does the transform chain order actually change?

Everything about composition. Transforms apply right to left to the element's local coordinates: translate(100px) rotate(45deg) moves the element 100px and then spins it in place, while rotate(45deg) translate(100px) spins first and then moves 100px along the ROTATED axis - so the element lands 100px along a diagonal instead of horizontally. Same functions, different order, different destination. When a chain confuses you, read it as instructions to a person holding the element: 'move right 100px, then turn 45 degrees' is the reverse order of 'turn, then move'.

Why are translate percentages relative to the element itself?

By specification - and it is the property that makes the classic centering trick work. translate(-50%, -50%) shifts the element left and up by HALF ITS OWN size, which exactly cancels the top-left anchor placement at 50%/50% of the parent, for any element size, without JavaScript. Margin-based centering needs known dimensions; translate centering does not. The contrast to remember: percentage values in width or margin resolve against the PARENT; percentage in translate resolves against the element being transformed.

When do I need the 3d functions and perspective?

When depth is the design: card flips (rotateY with a backface), parallax layers, tilt effects. The rule that unlocks them: 3d transforms only look three-dimensional when some ancestor establishes perspective - parent { perspective: 800px } - otherwise rotateY just looks like a horizontal squeeze, because there is no vanishing point. translateZ moves toward that viewer. The cost note: perspective and 3d transforms promote their own compositing layers, so they share the GPU economics of 2d transforms, but preserve-3d and nested 3d contexts get hairy fast - keep the 3d scene shallow.

Related tools