If you've ever tried to extract gradient data from Figma's API, you've probably encountered cryptic transformation matrices like [[-0.5, 0.5, 0.5], [-0.5, -0.5, 1]] and wondered what on earth these numbers mean. After diving deep into this rabbit hole, I'm here to save you the hours of confusion I went through.
When you fetch a gradient from Figma's API, you get something like this:
{
type: 'GRADIENT_LINEAR',
gradientTransform: [
[-0.08691141754388809, 0.09161579608917236, 0.5163052678108215],
[-0.09161579608917236, -0.08691141754388809, 0.5846190452575684]
],
gradientStops: [
{ color: { r: 0, g: 0, b: 0, a: 1 }, position: 0 },
{ color: { r: 1, g: 1, b: 1, a: 1 }, position: 1 }
]
}
Those gradientTransform values? They're not pixel coordinates. They're not percentages. They're not even directly related to where you placed the gradient handles in Figma. They're a 3x2 affine transformation matrix.
Each gradient transform consists of two rows with three values each:
[a, b, tx] // First row
[c, d, ty] // Second row
This matrix transforms gradient coordinates through:
a, d: Scaling factorsb, c: Rotation and skewtx, ty: Translation (position offset)The gradient operates in a normalized coordinate space where:
Here's what tripped me up: the gradient handles you see in Figma don't directly map to these transform values. Instead:
For example, a diagonal gradient that looks centered might have ty = 0.96 because the transformation needs to compensate for the rotation to keep the gradient visually centered.
Thankfully, Figma provides an official helper that makes this manageable:
import { extractLinearGradientParamsFromTransform } from "@figma-plugin/helpers";
// Convert matrix to readable handle positions
const params = extractLinearGradientParamsFromTransform(gradientTransform);
// Returns: { start: {x, y}, end: {x, y}, width }
// Now you have intuitive values!
console.log(`Gradient from ${params.start.x},${params.start.y} to ${params.end.x},${params.end.y}`);
Install it with:
npm install @figma-plugin/helpers
Here's a complete function to convert Figma gradients to CSS:
function figmaGradientToCSS(paint, elementWidth = 100, elementHeight = 100) {
const { extractLinearGradientParamsFromTransform } = require('@figma-plugin/helpers');
const params = extractLinearGradientParamsFromTransform(paint.gradientTransform);
// Calculate angle from start/end points
const dx = params.end.x - params.start.x;
const dy = params.end.y - params.start.y;
const angle = Math.atan2(dy * elementHeight, dx * elementWidth) * 180 / Math.PI;
// Convert color stops to CSS format
const stops = paint.gradientStops.map(stop => {
const r = Math.round(stop.color.r * 255);
const g = Math.round(stop.color.g * 255);
const b = Math.round(stop.color.b * 255);
const a = stop.color.a;
return `rgba(${r}, ${g}, ${b}, ${a}) ${stop.position * 100}%`;
});
return `linear-gradient(${angle}deg, ${stops.join(', ')})`;
}
Through experimentation, here's what different gradient configurations look like:
// Horizontal gradient (left to right)
// Transform: [[1, 0, 0], [0, 1, 0]]
// Extracted: { start: {x: 0, y: 0.5}, end: {x: 1, y: 0.5} }
// Vertical gradient (top to bottom)
// Transform: [[0, 1, 0], [-1, 0, 1]]
// Extracted: { start: {x: 0.5, y: 0}, end: {x: 0.5, y: 1} }
// Diagonal gradient
// Transform: [[-0.5, 0.5, 0.5], [-0.5, -0.5, 1]]
// Extracted: { start: {x: 0, y: 1}, end: {x: 1, y: 0} }
Sometimes you'll see gradients that extend beyond the shape boundaries. These have smaller scale values in the transform matrix:
// Gradient extends beyond bounds
// Transform has small scale factors like 0.09
// This creates softer, more subtle transitions
function isGradientOutOfBounds(transform) {
const params = extractLinearGradientParamsFromTransform(transform);
return params.width > 1.5; // Arbitrary threshold
}
If you need to create gradient transforms:
// Hypothetical function (check if Figma provides this)
import { createLinearGradientTransform } from "@figma-plugin/helpers";
const transform = createLinearGradientTransform(
{ x: 0, y: 0 }, // start point
{ x: 1, y: 1 }, // end point
1.0 // width/scale
);
@figma-plugin/helpers?extractLinearGradientParamsFromTransform()?Working with Figma gradients programmatically can be frustrating at first, but once you understand that these transforms are standard affine matrices and use the right helper functions, it becomes manageable. The key is not trying to manually interpret the matrix values - let Figma's helpers do the heavy lifting.

Philipp is Lead Developer in the Levels team. He graduated from the renowned University of Applied Sciences in Hagenberg and has been a freelance web developer for over 15 years with extensive experience in custom coding, digital product development, process optimisation and automation.