translate() – Moving Elements
Moves an element from its current position. Unlike top/left/margin, translate doesn't trigger layout reflow.
/* translate(x, y) */
transform: translate(20px, 40px); /* 20px right, 40px down */
transform: translate(-50%, -50%); /* center trick (see below) */
transform: translate(0, -8px); /* lift 8px up */
/* Single axis shorthand */
transform: translateX(100px); /* horizontal only */
transform: translateY(-20px); /* vertical only */
transform: translateZ(50px); /* depth (3D only) */
/* Modern individual properties (no need to wrap in transform) */
translate: 20px 40px; /* CSS individual transform property */
translate: -50% -50%;
/* The classic centering trick */
.centered {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* top/left move the top-left corner to center of parent
translate(-50%, -50%) then offsets back by half its own size */
}
scale() – Resizing Elements
/* scale(x, y) — 1 = original size */
transform: scale(1.2); /* 120% — both axes */
transform: scale(1.5, 0.8); /* wider, shorter */
transform: scale(0.5); /* 50% — shrink */
transform: scale(-1); /* flip both axes (mirror) */
/* Single axis */
transform: scaleX(2); /* double width */
transform: scaleY(0.5); /* half height */
/* Modern individual property */
scale: 1.1;
scale: 1.5 0.8;
/* Button hover: slight scale up */
.btn:hover { transform: scale(1.05); }
/* Flip horizontally (mirror image) */
.rtl-icon { transform: scaleX(-1); }
rotate() – Rotating Elements
/* rotate(angle) — positive = clockwise */
transform: rotate(45deg); /* 45 degrees clockwise */
transform: rotate(-90deg); /* 90 degrees counter-clockwise */
transform: rotate(0.5turn); /* half turn = 180deg */
transform: rotate(3.14159rad); /* radians */
/* 3D rotation */
transform: rotateX(30deg); /* tilt forward/backward */
transform: rotateY(45deg); /* spin around vertical axis */
transform: rotateZ(30deg); /* same as rotate(30deg) */
transform: rotate3d(1, 1, 0, 45deg); /* arbitrary axis */
/* Modern individual property */
rotate: 45deg;
/* Spinning loader */
@keyframes spin { to { rotate: 360deg; } }
/* or */
@keyframes spin { to { transform: rotate(360deg); } }
/* Chevron arrow toggle */
.chevron { transition: rotate 0.3s ease; }
.open .chevron { rotate: 180deg; }
skew() – Distorting Elements
transform: skew(20deg); /* skew on X axis */
transform: skew(10deg, 5deg); /* skew both axes */
transform: skewX(15deg); /* horizontal shear */
transform: skewY(10deg); /* vertical shear */
/* Angled section divider */
.section-divider {
transform: skewY(-3deg);
}
.section-divider > * {
transform: skewY(3deg); /* counter-skew content so text stays upright */
}
Combining Transforms
List multiple functions space-separated. Order matters — transforms are applied right to left.
/* Order matters: each transform is relative to the previous */
transform: translateY(-8px) scale(1.05); /* lift then scale */
transform: rotate(45deg) scale(0.7); /* rotate then shrink */
transform: translateX(-50%) translateY(-50%); /* center centering */
/* Wrong order can produce unexpected results */
transform: scale(2) translateX(10px); /* translate 10px in scaled space = 20px visually */
transform: translateX(10px) scale(2); /* translate 10px in original space, then scale */
/* Individual properties (order independent, applied separately) */
translate: 0 -8px;
scale: 1.05;
rotate: 0deg;
/* These are always applied in order: translate → rotate → scale */
transform-origin – Pivot Point
Controls the point around which transforms are applied. Default is 50% 50% (center).
transform-origin: center; /* default — 50% 50% */
transform-origin: top left; /* 0% 0% — rotate from corner */
transform-origin: bottom center; /* 50% 100% */
transform-origin: 20px 40px; /* exact pixel from top-left */
transform-origin: right; /* 100% 50% */
/* Practical example: tooltip scale from its tip */
.tooltip {
transform-origin: bottom center; /* grows from the bottom-center */
transform: scale(0);
transition: transform 0.2s ease;
}
.tooltip.visible { transform: scale(1); }
/* Page-turn effect: rotate from left edge */
.page {
transform-origin: left center;
transform: rotateY(-90deg);
}
3D Transforms and perspective
/* perspective defines depth — lower = more dramatic 3D effect */
/* Applied to the PARENT container */
.scene {
perspective: 800px;
perspective-origin: 50% 50%; /* viewpoint position */
}
/* 3D transforms on the child */
.card {
transform: rotateY(30deg);
transform-style: preserve-3d; /* children also in 3D space */
}
/* Card flip effect */
.card-inner {
position: relative;
transform-style: preserve-3d;
transition: transform 0.6s ease;
}
.card-inner.flipped { transform: rotateY(180deg); }
.card-front, .card-back {
position: absolute;
inset: 0;
backface-visibility: hidden; /* hide the reverse side */
}
.card-back { transform: rotateY(180deg); }
📋 Summary
- translate(x, y) — move without reflow.
translate(-50%, -50%)for centering. - scale(n) — resize visually.
scale(-1)to flip/mirror. - rotate(deg) — clockwise for positive values. Use
turnunit for readability. - skew(deg) — shear/distort. Use for angled section dividers.
- Combine with space-separated list. Order is right-to-left application.
- transform-origin — pivot point. Default: center. Change for corner rotations or tooltip growth.
- Individual properties (
translate:,scale:,rotate:) apply in fixed order: translate → rotate → scale. - perspective on parent — enables 3D depth effect on children.
- backface-visibility: hidden — hides the back of a flipped element.
- Transform + opacity = GPU compositor only — always 60fps, no layout reflow.
Frequently Asked Questions
Changing top or left triggers layout reflow — the browser recalculates all element positions. This is expensive and can cause jank (stuttering). Changing transform: translate only triggers the compositor layer — the GPU handles it directly without any layout or paint work. On most devices, this means the difference between 15fps and 60fps for animations. Always use transform: translateX/translateY instead of left/top for anything animated.
No — transforms are purely visual. The element keeps its original space in the document flow as if the transform didn't exist. Adjacent elements don't move when you translate or scale something. This is both a feature (won't break layout) and a potential confusion (a translated element may visually overlap other elements without those elements reflowing). Use transforms for visual effects and animations, not for repositioning elements in the layout — use flexbox/grid/position for actual layout changes.
Individual properties (translate, rotate, scale) are applied in a fixed order: translate first, then rotate, then scale — regardless of the order you write them. The transform shorthand applies functions in the order you write them (right to left). Individual properties also don't interfere with each other — animating rotate via keyframes while also using transform: scale() on hover works cleanly with individual properties but would conflict with the shorthand.