DEV Community

Michael Lip
Michael Lip

Posted on • Originally published at zovo.one

CSS Gradients: Why Your Color Transitions Look Muddy and How to Fix Them

CSS gradients should be simple. Pick two colors, set a direction, done. But if you have ever created a gradient between two vibrant colors and gotten a murky grey band in the middle, you know it is not that straightforward.

The problem is color interpolation, and understanding it makes the difference between gradients that look professional and gradients that look like they were generated by accident.

Why gradients go grey

When the browser interpolates between two colors in a gradient, it calculates intermediate values for each color channel. In the default sRGB color space, this interpolation follows straight lines through the RGB cube.

The problem: the straight line between blue (#0000FF) and yellow (#FFFF00) in RGB space passes through grey. The midpoint is approximately #808080 -- literally grey.

This happens because the RGB color model does not map to human color perception. Perceptually different colors can be close in RGB space, and perceptually similar colors can be far apart.

The fix is to interpolate in a different color space. Modern CSS supports this:

/* Muddy transition in sRGB */
.gradient-srgb {
  background: linear-gradient(to right, blue, yellow);
}

/* Vibrant transition in oklch */
.gradient-oklch {
  background: linear-gradient(in oklch to right, blue, yellow);
}
Enter fullscreen mode Exit fullscreen mode

The in oklch syntax tells the browser to interpolate in the OKLCH perceptual color space, which produces vibrant, natural-looking transitions because it follows the path through "colorful" colors rather than through grey.

Gradient types

CSS supports three gradient functions:

linear-gradient(): Transitions along a straight line.

background: linear-gradient(135deg, #667eea, #764ba2);
Enter fullscreen mode Exit fullscreen mode

The angle defines the direction. 0deg is bottom-to-top, 90deg is left-to-right, 135deg is top-left to bottom-right. You can also use keyword directions: to right, to bottom left, etc.

radial-gradient(): Transitions outward from a center point.

background: radial-gradient(circle at 30% 50%, #667eea, #764ba2);
Enter fullscreen mode Exit fullscreen mode

The shape can be circle or ellipse. The position (at 30% 50%) defines the center. Default is ellipse at center.

conic-gradient(): Transitions around a center point, like a color wheel.

background: conic-gradient(from 0deg at 50% 50%, #667eea, #764ba2, #667eea);
Enter fullscreen mode Exit fullscreen mode

Conic gradients are underused but perfect for pie charts, color pickers, and radial progress indicators.

Color stop positioning

By default, color stops are evenly distributed. But you can position them explicitly to control the transition:

/* Blue dominates most of the gradient */
background: linear-gradient(
  to right,
  #667eea 0%,
  #667eea 60%,
  #764ba2 100%
);
Enter fullscreen mode Exit fullscreen mode

Two stops at the same position create a hard edge:

/* Sharp color boundary at 50% */
background: linear-gradient(
  to right,
  #667eea 50%,
  #764ba2 50%
);
Enter fullscreen mode Exit fullscreen mode

You can also use color hints (midpoints) to shift where the transition's halfway point falls:

background: linear-gradient(
  to right,
  #667eea,
  30%,  /* midpoint at 30% instead of 50% */
  #764ba2
);
Enter fullscreen mode Exit fullscreen mode

Multi-stop gradients for depth

Simple two-color gradients look flat. Adding an intermediate stop creates perceived depth:

/* Flat */
background: linear-gradient(135deg, #667eea, #764ba2);

/* Rich with depth */
background: linear-gradient(
  135deg,
  #667eea 0%,
  #5a67d8 30%,
  #764ba2 100%
);
Enter fullscreen mode Exit fullscreen mode

The intermediate color should be a blend that maintains vibrancy. Picking it by eye or using a perceptual color space produces better results than simple averaging.

The generator

Building multi-stop gradients with precise color stop positions, angles, and color space interpolation through hand-written CSS requires endless refresh cycles. I built a CSS gradient generator that gives you visual control over every parameter with real-time preview and copyable CSS output.


I'm Michael Lip. I build free developer tools at zovo.one. 500+ tools, all private, all free.

Top comments (0)