Free · Fast · Privacy-first

CSS matrix() Transform

The CSS matrix() function encodes a complete 2D transform as a single six-value mathematical matrix.

Input individual rotate, translate, scale, and skew values

🔒

Outputs the equivalent matrix() or matrix3d() declaration

Annotated breakdown of what each matrix position represents

Copy-ready output for both function lists and matrix forms

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Transform Gen to your website

Drop the Transform Gen into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

Embed code

<iframe
  src="https://www.fixtools.io/css-tool/transform-gen?embed=1"
  width="100%"
  height="780"
  frameborder="0"
  style="border:0;border-radius:16px;max-width:900px;"
  title="Transform Gen by FixTools"
  loading="lazy"
  allow="clipboard-write"
></iframe>

Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.

What the Six Values in CSS matrix() Mean and How to Convert Transform Functions to a Matrix

The CSS matrix(a, b, c, d, tx, ty) function takes six values that map to a 3x3 transformation matrix applied in homogeneous coordinates. The values a and d control scale: a is the X scale and d is the Y scale. For no scale change, both are 1. The values b and c control skew: b is the Y-axis skew factor and c is the X-axis skew factor. For a pure rotation by angle θ, a equals cos(θ), b equals sin(θ), c equals -sin(θ), and d equals cos(θ). For a pure translation, tx is the X offset in pixels and ty is the Y offset in pixels. A transform that does nothing is matrix(1, 0, 0, 1, 0, 0), which is the identity matrix. Any combination of rotate, scale, translate, and skew can be reduced to a single set of these six values by multiplying the individual matrices together.

The matrix3d() function takes sixteen values that form a 4x4 matrix in column-major order. The first four values are the first column, the next four are the second column, and so on. The identity matrix3d is matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1). The top-left 3x3 submatrix (values 1, 2, 3, 5, 6, 7, 9, 10, 11) controls rotation and scale. Values 13, 14, and 15 control X, Y, and Z translation. Value 16 is the perspective division factor, which is 1 for affine transforms and a non-zero value for perspective transforms. Understanding the column-major ordering is critical when constructing matrix3d values by hand, as confusion over row vs column order is the most common source of incorrect transforms.

JavaScript animation libraries and browser APIs like DOMMatrix and getComputedStyle return transform values in matrix form. getComputedStyle(element).transform on a rotated element returns a string like matrix(0.866, 0.5, -0.5, 0.866, 0, 0) rather than rotate(30deg). Being able to read and decompose this output is essential for JavaScript-driven animations that need to continue from the current computed transform state without resetting to zero. The DOMMatrix API provides a programmatic interface for creating, multiplying, and decomposing matrices, which complements the CSS matrix() syntax.

Matrix transforms run on the GPU compositor the same as any other transform value, but they have one quirk worth understanding. When the browser sees a matrix3d() value with a non-identity perspective component (position 16 is not 1), it forces a 3D rendering context on the element regardless of whether the perspective property is set on a parent. This implicit promotion costs GPU memory equal to the bounding box at the device pixel ratio. For elements that animate matrix3d values frequently, declare will-change: transform so the layer is prepared once rather than reallocated on every animation start, and remove it when the animation completes. Engines differ in how aggressively they cache the resulting layer texture, with Chromium being the most generous and Firefox the most conservative on memory pressure.

How to use this tool

💡

Enter values in the decomposed controls: rotation angle, X and Y translation, X and Y scale, and X and Y skew. The generator computes the equivalent matrix() values in real time and previews the transform. Switch between the expanded function list and the single matrix() output using the format toggle.

How It Works

Step-by-step guide to css matrix() transform:

  1. 1

    Enter decomposed transform values

    Type rotation, translation, scale, and skew values in the labeled fields. The generator computes the equivalent matrix() in real time.

  2. 2

    Review the matrix output

    Read the annotated breakdown showing which position in the matrix corresponds to which transform component. The preview element applies the matrix transform.

  3. 3

    Toggle output format

    Switch between the expanded transform function list and the single matrix() form. Both produce identical visual results.

  4. 4

    Copy the matrix declaration

    Click Copy Code to copy the matrix() or matrix3d() declaration. Paste it into your CSS file or JavaScript style assignment.

Real-world examples

Common situations where this approach makes a real difference:

Reading and continuing a running animation

A JavaScript animation library needs to interrupt a CSS animation and continue the transform from its current state. getComputedStyle(element).transform returns a matrix() string. The developer uses the generator to parse the string values and decompose the rotation angle and translation. The DOMMatrix API is then used to create a new matrix from the current state and animate from there, preventing the element from snapping back to its origin before the new animation begins.

Programmatically generated SVG-style transforms

A data visualization component generates CSS transforms for dozens of elements based on data values. The developer pre-computes all rotation and translation values in JavaScript, converts each combination to a matrix() string using DOMMatrix, and writes the matrix declarations into a style sheet as CSS custom properties. This avoids the overhead of the browser parsing function lists for every element update.

Cross-framework transform compatibility

A design token export system generates CSS transforms that must work in both a web CSS file and a React Native stylesheet. React Native uses matrix arrays rather than CSS transform function lists. The developer uses the generator to convert design-specified rotation and scale values into matrix() form for CSS and simultaneously exports the same values as a sixteen-element flat array for React Native matrix transforms.

Debugging unexpected element positions

An element in a complex component has an unexpected visual position that does not match its declared transform. The developer reads the computed transform from DevTools, which returns a matrix() string. They paste the six values into the generator's matrix decomposition tool to extract the actual rotation angle and translation distance. The decomposed values reveal that an inherited transform from a parent was being composed into the computed matrix, causing the unexpected offset.

Pro tips

Get better results with these expert suggestions:

1

Matrix multiplication order matches transform function order

Chaining transform functions in CSS is equivalent to multiplying their matrices left to right. rotate(45deg) translate(100px, 0) multiplies the rotation matrix by the translation matrix in that order. The final matrix() value the browser computes is the product. If you construct transforms programmatically using matrix multiplication, the order of multiplication must match the order of the function list to produce the same result.

2

Use matrix3d for combining 2D and 3D transforms efficiently

When an element needs both 2D and 3D transforms such as a rotation plus a Z translation, using a single matrix3d() that encodes all values is more explicit than mixing rotate() and translateZ() in a function list. The browser performs the same matrix multiplication internally, but an explicit matrix3d is more portable when the values are generated by code.

3

Decompose a computed matrix to extract rotation angle

Given a CSS matrix(a, b, c, d, tx, ty), the rotation angle is Math.atan2(b, a) in radians, converted to degrees by multiplying by 180/Math.PI. The X scale is Math.sqrt(a*a + b*b) and Y scale is Math.sqrt(c*c + d*d). This decomposition is useful in animation code that needs to read the current rotation from a computed transform and increment it.

4

Column-major order in matrix3d is a frequent source of bugs

matrix3d takes values in column-major order: the first four values are the first column of the 4x4 matrix, not the first row. If you are constructing a matrix3d from a row-major representation such as a math library output, you must transpose the values before using them in CSS. Transposing means swapping values at position [i][j] with values at position [j][i] across the diagonal.

5

Use DOMMatrix to compose transforms programmatically

The DOMMatrix API in JavaScript lets you create, multiply, and read transform matrices without manual trigonometry. Create a matrix with new DOMMatrix(), apply rotate(), translate(), and scale() methods, then read the .toString() result to get a CSS-compatible matrix() or matrix3d() string for use in inline styles or CSS custom properties.

6

getComputedStyle returns matrix form, not function list

When you read an element's computed transform via getComputedStyle(el).transform, the browser returns the resolved matrix value regardless of what functions you specified in the CSS. For a JavaScript animation that reads and continues from the current transform, parse this matrix string rather than reading the original CSS property.

7

The identity matrix leaves elements unchanged

matrix(1, 0, 0, 1, 0, 0) is the identity matrix for 2D transforms. Applying it produces no visual change. It is equivalent to transform: none. Explicitly setting an element to the identity matrix in an animation start state ensures the transition starts from a known baseline regardless of any inherited transforms.

FAQ

Frequently asked questions

matrix(a, b, c, d, tx, ty) encodes a 2D affine transform. The value a is the X scale and horizontal cos component, b is the Y skew and vertical sin component, c is the X skew and horizontal negative-sin component, d is the Y scale and vertical cos component, tx is the X translation in pixels, and ty is the Y translation in pixels. For a pure rotation by angle θ, the values are cos(θ), sin(θ), -sin(θ), cos(θ), 0, 0. For no transform, the identity is matrix(1, 0, 0, 1, 0, 0).
Calculate cos(30°) and sin(30°). cos(30°) is approximately 0.866 and sin(30°) is 0.5. The matrix() form is matrix(0.866, 0.5, -0.5, 0.866, 0, 0). The a and d positions hold the cosine, b holds the positive sine, and c holds the negative sine. The tx and ty values are 0 because there is no translation. If you add a translation, place the X offset in tx and the Y offset in ty.
Use matrix() when you are generating transform values programmatically from code, when you want to combine multiple transforms into a single value for performance, or when you are reading and applying computed transforms from getComputedStyle. For hand-authored CSS, individual functions like rotate(), translate(), and scale() are more readable and maintainable. matrix() is primarily a machine-friendly format that browsers produce internally and that JavaScript animation libraries use.
The identity matrix is matrix(1, 0, 0, 1, 0, 0) for 2D and matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1) for 3D. Applying the identity matrix to an element produces no change: it is mathematically equivalent to transform: none. Setting an element to the identity matrix in an animation is useful for explicitly establishing a no-transform baseline state, particularly in JavaScript animations that set inline styles and need a known starting point.
The 2D matrix() form supports translate, rotate, scale, and skew. It does not support 3D transforms. For 3D transforms including rotateX, rotateY, translateZ, and perspective, use matrix3d(). The matrix3d() form encodes all 2D and 3D affine transforms in its sixteen values. Any combination of 2D and 3D CSS transform functions can be expressed as a single matrix3d() call.
matrix3d() takes sixteen values that form a 4x4 matrix in column-major order. It encodes any combination of 3D translation, rotation, scale, skew, and perspective. The values are read as four columns of four: columns 1 through 4 occupy positions 1-4, 5-8, 9-12, and 13-16 respectively. The translation values are at positions 13 (X), 14 (Y), and 15 (Z). The scale and rotation values are in the upper 3x3 submatrix. Position 16 is the perspective division factor.
Use getComputedStyle(element).transform to read the resolved transform value. This returns a string in matrix() or matrix3d() format regardless of how the transform was specified in CSS. To work with the matrix values programmatically, create a DOMMatrix from the string: new DOMMatrix(getComputedStyle(element).transform). The DOMMatrix object exposes individual matrix components as properties and provides methods for transforming points, rotating, and translating.
Yes. The browser can interpolate between two matrix() values in a CSS transition or animation. The interpolation decomposes each matrix into its translation, rotation, and scale components, interpolates each independently, and recomposes the result. This produces smooth animation between two matrix states. If the decomposition of either matrix is ambiguous, such as when the determinant is zero, the interpolation may produce unexpected results. Keeping matrix values within the range of typical transform functions avoids decomposition edge cases.
Wrap your matrix-driven transition or @keyframes invocation in an @media (prefers-reduced-motion: no-preference) block so the animation only runs for users who have not opted out. For users who prefer reduced motion, jump directly to the final matrix value without transitioning, or fall back to a simple opacity change that conveys the same state without lateral or rotational motion. Matrix interpolation between complex states can produce surprising in-between frames that decompose into mixed rotation and skew, which is particularly disorienting. A static end state is the safest fallback when motion is restricted. The media query is supported in all modern browsers.
Yes. A matrix3d transform creates a new stacking context the same as any other transform value. If the parent also declares transform-style: preserve-3d, descendants are stacked by their computed Z position rather than by z-index alone. A child with high z-index sitting at the same Z depth as a sibling with lower z-index but greater translateZ will render behind the closer sibling because depth ordering wins. To get predictable z-index behavior, remove preserve-3d and let the browser flatten the children, or move floating elements that rely on z-index out of the preserve-3d container via a DOM portal that mounts them as siblings of the application root rather than descendants of the 3D scene.

Related guides

More use-case guides for the same tool:

Ready to get started?

Open the full Transform Gen — free, no account needed, works on any device.

Open Transform Gen →

Free · No account needed · Works on any device