CSS matrix and matrix3d Functions Explained
The CSS matrix() and matrix3d() functions
provide a low-level method for applying affine transformations directly
to HTML elements using mathematical matrices. Rather than chaining
individual functions like rotate(), scale(),
translate(), and skew(), these functions
combine all geometric alterations into a single set of values. This
article covers how 2D and 3D transformation matrices work, the parameter
structure for both functions, and how they translate to visual
manipulations in web browsers.
Understanding Affine Transformations
An affine transformation is a linear mapping method that preserves
points, straight lines, and planes. In CSS, affine transformations alter
an element’s position, size, orientation, and shear without curving
parallel lines. Standard CSS transform utilities—such as
translateX(20px) or rotate(45deg)—are simply
human-readable abstractions. Under the hood, the browser translates all
transform rules into an affine transformation matrix to render the
element on the screen.
The 2D matrix()
Function
The matrix() function handles two-dimensional
transformations using a 3×3 matrix. Because the bottom row of an affine
matrix in 2D homogeneous coordinates is always [0, 0, 1],
CSS exposes only the six dynamic values:
transform: matrix(a, b, c, d, tx, ty);The underlying mathematical representation corresponds to:
| a c tx |
| b d ty |
| 0 0 1 |
Each parameter governs specific spatial properties:
a(Scale X): Stretches or shrinks the element horizontally. A value of1represents default size.b(Skew Y): Vertically shears the element based on the angle's tangent.c(Skew X): Horizontally shears the element based on the angle's tangent.d(Scale Y): Stretches or shrinks the element vertically. A value of1represents default size.tx(Translate X): Moves the element along the X-axis in pixels.ty(Translate Y): Moves the element along the Y-axis in pixels.
For example, to translate an element by 50px horizontally and scale it by 1.5 times in both directions:
transform: matrix(1.5, 0, 0, 1.5, 50, 0);The 3D matrix3d()
Function
To manipulate elements in three-dimensional space, CSS uses
matrix3d(). This function takes a 4×4 transformation matrix
defined by 16 arguments listed in column-major order:
transform: matrix3d(
a1, b1, c1, d1,
a2, b2, c2, d2,
a3, b3, c3, d3,
a4, b4, c4, d4
);In matrix form, this layout appears as follows:
| a1 a2 a3 a4 |
| b1 b2 b3 b4 |
| c1 c2 c3 c4 |
| d1 d2 d3 d4 |
These values manage distinct components of 3D rendering:
- Columns 1 to 3 (
a1throughc3): Manage linear transformations, including 3D rotations, non-uniform scaling across the X, Y, and Z axes, and multi-directional shearing. - Fourth Column (
a4,b4,c4): Represents the translation components (translateX,translateY,translateZ). - Fourth Row (
d1,d2,d3,d4): Controls perspective projection and homogeneous scaling. For standard affine transforms,d1,d2, andd3remain0, whiled4acts as a global scale factor typically set to1.
An identity matrix in 3D—which applies no visual changes—is written as:
transform: matrix3d(
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
);When to Use Raw Matrix Functions
While functions like rotate() and
translate() are easier to read and maintain for simple
layouts, matrix() and matrix3d() offer
distinct advantages in specialized scenarios:
- Performance in Animation Engines: JavaScript animation and physics libraries (such as GSAP, Three.js, or custom canvas engines) compute compound transforms using matrix multiplication. Passing a single calculated matrix string to the CSS engine reduces the parsing overhead of resolving multiple chained functions.
- Precision and Synchronization: Interpolating between complex orientations—especially in 3D—can introduce gimbal lock or unexpected visual artifacts when animating individual rotation axes. Matrix representation allows continuous, deterministic frame-by-frame updates.
- Complex Deformations: Non-standard spatial mappings, such as combined perspective warps and directional skews, can be calculated programmatically and applied via a single declaration without relying on multiple nested wrapper elements.