Transforms & motion path
The properties that move, rotate, scale and skew a box after layout, place it in 3D space, or send it along a path. Transforms change how a box is painted, not where it sits in the layout, so neighbouring content does not move. The functions that go inside transform (translate(), rotate(), matrix() and the rest) are under Transform functions; animating these properties is covered in Transitions & animation.
Transforms
transform
Applies a list of transform functions to a box. The functions are applied in order, so translate(10px) rotate(45deg) and rotate(45deg) translate(10px) give different results.
| Syntax | none | <transform-list> |
|---|---|
| Initial | none |
| Applies to | Transformable elements |
| Inherited | No |
| Percentages | Refer to the size of the reference box |
| Animation | As a transform list, following the transform interpolation rules |
| Support | Chrome 36 · Firefox 16 · Safari 9 |
| Spec | css-transforms-1 |
A <transform-list> is one or more transform functions separated by spaces. Any value other than none makes the box a containing block for its absolutely and fixed positioned descendants and creates a stacking context.
transform: translate(-50%, -50%) rotate(-3deg);
transform-origin
The fixed point that transforms happen around: the centre of a rotation or scale. One or two values set the x and y position like background-position; an optional third length sets the z position.
| Syntax | [ left | center | right | top | bottom | <length-percentage> ] | [ left | center | right | <length-percentage> ] [ top | center | bottom | <length-percentage> ] <length>? | [ [ center | left | right ] && [ center | top | bottom ] ] <length>? |
|---|---|
| Initial | 50% 50% |
| Applies to | Transformable elements |
| Inherited | No |
| Percentages | Refer to the size of the reference box |
| Animation | By computed value |
| Support | Chrome 36 · Firefox 16 · Safari 9 |
| Spec | css-transforms-1 |
It also applies to the individual translate, rotate and scale properties. transform-origin: top left makes a box rotate around its top-left corner.
transform-box
Chooses the reference box that transform-origin and percentage values in transforms are measured against. It matters mostly for SVG elements, where the default measures from the SVG viewport rather than the shape itself.
| Syntax | content-box | border-box | fill-box | stroke-box | view-box |
|---|---|
| Initial | view-box |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | Discrete |
| Support | Chrome 64 · Firefox 55 · Safari 11 |
| Spec | css-transforms-1 |
For elements with a CSS layout box, fill-box is used as content-box, and stroke-box and view-box are used as border-box. So on HTML elements the default is the border box.
svg .gear { transform-box: fill-box; transform-origin: center; }
Individual transforms
translate
Moves a box without writing a full transform. One value moves along x; two move along x and y; a third length moves along z.
| Syntax | none | <length-percentage> [ <length-percentage> <length>? ]? |
|---|---|
| Initial | none |
| Applies to | Transformable elements |
| Inherited | No |
| Percentages | Relative to the width of the reference box (first value) or its height (second value) |
| Animation | By computed value; none is treated as no translation |
| Support | Chrome 104 · Firefox 72 · Safari 14.1 |
| Spec | css-transforms-2 |
The individual properties combine with transform in a fixed order: translate, then rotate, then scale, then the transform list. Because each is its own property, a hover rule can change one of them without repeating or undoing the others, and each can be transitioned on its own timing.
.card { rotate: -2deg; transition: translate 0.2s; }
.card:hover { translate: 0 -4px; } /* the rotation is kept */
rotate
Rotates a box. A bare angle rotates in the plane of the screen; an axis keyword (x, y, z) or three numbers giving an axis vector, followed by an angle, rotates in 3D.
| Syntax | none | <angle> | [ x | y | z | <number>{3} ] && <angle> |
|---|---|
| Initial | none |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | As SLERP (spherical interpolation); none is treated as no rotation |
| Support | Chrome 104 · Firefox 72 · Safari 14.1 |
| Spec | css-transforms-2 |
rotate: y 180deg;
scale
Scales a box. One value scales both x and y equally; two scale x and y separately; a third scales z.
| Syntax | none | [ <number> | <percentage> ]{1,3} |
|---|---|
| Initial | none |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | By computed value; none is treated as no scaling |
| Support | Chrome 104 · Firefox 72 · Safari 14.1 |
| Spec | css-transforms-2 |
A percentage is the same as the matching number: scale: 150% equals scale: 1.5. A negative value mirrors the box in that axis.
3D
perspective
Gives an element's children a 3D viewing distance, so their 3D transforms show depth: things further away look smaller. Smaller lengths give a stronger, closer effect.
| Syntax | none | <length [0,∞]> |
|---|---|
| Initial | none |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | By computed value |
| Support | Chrome 36 · Firefox 16 · Safari 9 |
| Spec | css-transforms-2 |
The property affects the element's children, all seen from one shared viewpoint. The perspective() transform function affects only the element it is applied to.
perspective-origin
Where the viewer stands when looking at the 3D children of an element with perspective: the vanishing point. It takes a position like background-position.
| Syntax | <position> |
|---|---|
| Initial | 50% 50% |
| Applies to | Transformable elements |
| Inherited | No |
| Percentages | Refer to the size of the reference box |
| Animation | By computed value |
| Support | Chrome 36 · Firefox 16 · Safari 9 |
| Spec | css-transforms-2 |
transform-style
Whether an element's children share its 3D space (preserve-3d) or are flattened into its plane (flat). Use preserve-3d to build objects such as a cube from several faces.
| Syntax | flat | preserve-3d |
|---|---|
| Initial | flat |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | Discrete |
| Support | Chrome 36 · Firefox 16 · Safari 9 |
| Spec | css-transforms-2 |
Some properties force a flat result even when preserve-3d is set, because they need the element painted as one group first. Examples are opacity below 1, filter and overflow: hidden.
backface-visibility
Whether the back of a box shows when it is turned away from the viewer. Set hidden on both faces of a flip card so only the side facing the viewer is seen.
| Syntax | visible | hidden |
|---|---|
| Initial | visible |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | Discrete |
| Support | Chrome 36 · Firefox 16 · Safari 15.4 |
| Spec | css-transforms-2 |
.card { perspective: 800px; }
.card-inner { transform-style: preserve-3d; transition: rotate 0.5s; }
.card:hover .card-inner { rotate: y 180deg; }
.front, .back { backface-visibility: hidden; }
.back { rotate: y 180deg; }
Motion path
offset
Shorthand that places a box on a path: the path's start position, the path, how far along it the box sits and which way it faces, then after a slash the point of the box that sits on the path.
| Syntax | [ <'offset-position'>? [ <'offset-path'> [ <'offset-distance'> || <'offset-rotate'> ]? ]? ]! [ / <'offset-anchor'> ]? |
|---|---|
| Initial | See individual properties |
| Applies to | Transformable elements |
| Inherited | See individual properties |
| Percentages | See individual properties |
| Animation | See individual properties |
| Support | Chrome 55 · Firefox 72 · Safari 16 |
| Spec | motion-1 |
The ! after the first group means that group must not be empty: at least one of its parts has to be given. The motion path is applied as a transform, before the transform property and after the individual transform properties.
@keyframes along { to { offset-distance: 100%; } }
.dot {
offset: path('M 0 0 C 100 0 100 100 200 100') 0% auto;
animation: along 2s ease-in-out infinite alternate;
}
offset-path
The path a box is placed on. An <offset-path> is a ray(), a url() pointing at an SVG shape, or a basic shape such as path(), circle() or inset(). The optional <coord-box> sets the box that a basic shape is sized against.
| Syntax | none | <offset-path> || <coord-box> |
|---|---|
| Initial | none |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | By computed value |
| Support | Chrome 55 · Firefox 72 · Safari 15.4 |
| Spec | motion-1 |
offset-distance
How far along the path the box sits. Animate it from 0% to 100% to move a box from the start of the path to the end.
| Syntax | <length-percentage> |
|---|---|
| Initial | 0 |
| Applies to | Transformable elements |
| Inherited | No |
| Percentages | Relative to the length of the offset path |
| Animation | By computed value |
| Support | Chrome 55 · Firefox 72 · Safari 16 |
| Spec | motion-1 |
offset-rotate
Which way the box faces as it sits on the path. auto turns it to follow the direction of the path, reverse turns it the opposite way, and an angle adds a fixed rotation, on its own or on top of auto or reverse.
| Syntax | [ auto | reverse ] || <angle> |
|---|---|
| Initial | auto |
| Applies to | Transformable elements |
| Inherited | No |
| Animation | By computed value |
| Support | Chrome 56 · Firefox 72 · Safari 16 |
| Spec | motion-1 |
A bare angle such as 0deg keeps the box upright whichever way the path turns.
offset-anchor
The point of the box that is placed on the path. auto uses the transform-origin point, which is the centre by default.
| Syntax | auto | <position> |
|---|---|
| Initial | auto |
| Applies to | Transformable elements |
| Inherited | No |
| Percentages | Relative to the width and height of the element's reference box |
| Animation | By computed value |
| Support | Chrome 116 · Firefox 72 · Safari 16 |
| Spec | motion-1 |
offset-position
The starting point of a path that has no start of its own, such as a ray(). auto starts from the box's own position; normal starts from the centre of the containing block; a position places it in the containing block.
| Syntax | normal | auto | <position> |
|---|---|
| Initial | normal |
| Applies to | Transformable elements |
| Inherited | No |
| Percentages | Refer to the size of the containing block |
| Animation | By computed value |
| Support | Chrome 116 · Firefox 122 · Safari 16 |
| Spec | motion-1 |