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 of 1 represents 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 of 1 represents 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 (a1 through c3): 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, and d3 remain 0, while d4 acts as a global scale factor typically set to 1.

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:

  1. 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.
  2. 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.
  3. 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.