albert.walickihire me
← all solutions
ux/ui

Why do gradients from Figma or Sketch look different in the browser?

Gradients from Figma or Sketch often look off in CSS because of angle geometry, color profiles, sRGB blending and extra layers. Here's how to fix each one.

There are four usual causes, and often more than one applies: the angle maps differently on a box that isn't square, the design file uses a different color profile, the browser blends the colors in a different color space, and the design has extra layers that the copied CSS leaves out. A gradient with an adjusted angle and an explicit color space looks like this:

.hero {
  /* fallback for browsers without color interpolation */
  background: linear-gradient(153deg, #7c3aed, #f97316);
  background: linear-gradient(153deg in oklch, #7c3aed, #f97316);
}

The angle depends on the shape of the box

In CSS, linear-gradient(135deg, ...) fixes the angle, and the browser calculates the length of the gradient line from the size of the box so the corners get exactly the first and last colors. A design tool instead stores two handles placed on the layer, and the colors start and end exactly where those handles are. A corner-to-corner drag and 135deg only match on a square.

The keyword to bottom right isn't the same as 135deg either. It keeps the middle of the gradient on the line between the top-right and bottom-left corners, so its angle changes with the box. On a 400×200 card, it works out to about 153deg:

/* Identical on a square, different on a 400x200 card */
.card-a {
  background: linear-gradient(135deg, #2563eb, #facc15);
}

.card-b {
  background: linear-gradient(to bottom right, #2563eb, #facc15);
}

To fix it, check where the handles start and end in the design tool and compare with the browser at the same element size. Adjust the angle, and if the handles don't reach the edges of the layer, move the stops too, for example #2563eb 15%, #facc15 85%. CSS generated by an inspect panel or a plugin is a starting point, not the final answer.

Color profiles

Figma and Sketch documents have a color profile setting. In a Display P3 document, hex values are treated as P3 colors, which can be more saturated than anything sRGB can show. In CSS, a hex value is always sRGB, so the same #ff3366 looks duller in the browser on a wide-gamut screen.

Either switch the document to sRGB, or use P3 colors in CSS. To convert a P3 hex value, divide each channel by 255:

.hero {
  background: linear-gradient(#ff3366, #6633ff);
  background: linear-gradient(
    color(display-p3 1 0.2 0.4),
    color(display-p3 0.4 0.2 1)
  );
}

color() works in current major browsers, and on an sRGB screen the browser shows the closest color it can.

How the colors are blended

With hex, rgb() or hsl() colors, browsers blend gradients in sRGB. Between vivid colors on opposite sides of the color wheel, the middle turns gray and dark: blue #0000ff to yellow #ffff00 passes through #808080. Design tools don't necessarily blend the same way.

You can choose the color space in the gradient, as in the first snippet. in oklab keeps the lightness even, so the middle is less dark, but between opposite colors it still turns grayish. in oklch keeps the saturation by moving around the hue wheel: violet #7c3aed to orange #f97316 stays vivid through pink instead of a dusty #bb5782, and blue to yellow passes through teal. If that in-between hue doesn't match the design, add a middle stop with the design's color, which works in every browser.

Color interpolation in gradients is supported in current major browsers. Older ones drop the whole declaration and use the one before it, hence the fallback. Check Can I Use if you support older versions.

Layers the CSS doesn't include

A gradient in a design is often more than one fill: several stacked fills, a layer with reduced opacity, a blend mode or a noise texture. The copied CSS often includes only part of it, so check the layers panel. Stacked fills become multiple backgrounds, with the first one on top, and blend modes map to background-blend-mode or mix-blend-mode:

.hero {
  background:
    linear-gradient(rgb(255 255 255 / 0.2), transparent),
    linear-gradient(135deg, #2563eb, #7c3aed);
}

Large gradients between similar colors can show visible steps, called banding. That's often why the designer added noise, and a subtle noise image as an extra background layer breaks up the steps in the browser too.

Different screens

Recent MacBooks have wide-gamut P3 displays, and many external monitors are sRGB. A designer on a MacBook and a developer on an office monitor can look at the same gradient and see different colors, so compare on the same screen before calling it a bug.

Handoff tips

  • Agree on the document color profile. sRGB is the safe default unless you plan to use P3 colors in CSS.
  • Share stop positions along with the colors.
  • Point out opacity, blend modes and noise layers so they don't get lost.
  • Check gradients at the element's real sizes on narrow and wide screens, because the angle behaves differently.
  • Review the result in the browser, not only in the design file.
more solutions
work with me

Got something that needs building?

Frontend builds, full-stack features in Django, design-system work. Available for work.

See my workGet in touch