Pick colors, drag the stops, and copy the CSS gradient. Build a linear gradient at any angle or a radial one, with as many color stops as you need. The preview redraws on every slider move, so you see each change without reloading a page.
Linear gradients take an angle from 0 to 360 degrees. Radial gradients are drawn as a circle from the center, so the angle slider is disabled.
Add Stop appends another color, and each stop has its own position slider. The tool sorts stops by position before writing the CSS, so they never end up out of order.
background: linear-gradient(90deg, #3b82f6 0%, #8b5cf6 100%); You do not need vendor prefixes. The
output uses linear-gradient() and
radial-gradient(), which browsers have
supported unprefixed since around 2012, so the tool emits
one plain background declaration.
/* Linear: angle first, then stops with optional positions */
.hero {
background-image: linear-gradient(90deg, #ff7e5f 0%, #feb47b 100%);
}
/* Radial: shape and size, then stops */
.badge {
background-image: radial-gradient(circle at center, #2e3192 0%, #1bffff 100%);
}
/* Gradient text */
.title {
background-image: linear-gradient(135deg, #8e2de2, #4a00e0);
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
/* Hard stripe: two stops at the same position */
.stripe {
background-image: linear-gradient(90deg, #5a3f37 50%, #2c7744 50%);
} Use background-image rather than background if you also want to set a fallback background-color for old browsers.
const stops = [
{ color: "#ff7e5f", pos: 0 },
{ color: "#feb47b", pos: 100 },
];
function gradientCss(type, angle, stops) {
const list = [...stops]
.sort((a, b) => a.pos - b.pos)
.map((s) => `${s.color} ${s.pos}%`)
.join(", ");
return type === "radial"
? `radial-gradient(circle, ${list})`
: `linear-gradient(${angle}deg, ${list})`;
}
const css = gradientCss("linear", 90, stops);
console.log(css); // linear-gradient(90deg, #ff7e5f 0%, #feb47b 100%)
// Apply it in the browser
// document.querySelector(".hero").style.backgroundImage = css; Sorting the stops by position matters: CSS clamps an out-of-order stop to the previous one and the color vanishes.
# Generate a smooth multi-stop gradient between two colors
def hex_to_rgb(h):
h = h.lstrip("#")
return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))
def mix(a, b, t):
return tuple(round(x + (y - x) * t) for x, y in zip(a, b))
start, end, steps = hex_to_rgb("#2E3192"), hex_to_rgb("#1BFFFF"), 5
stops = []
for i in range(steps):
r, g, b = mix(start, end, i / (steps - 1))
stops.append(f"#{r:02x}{g:02x}{b:02x} {round(i * 100 / (steps - 1))}%")
print(f"background-image: linear-gradient(135deg, {', '.join(stops)});") Use this in build scripts that emit palettes. The browser already interpolates between two stops, so extra stops only matter when you want a custom curve.
A CSS gradient is an image with no intrinsic size. That explains most of its behavior: it belongs in background-image, it stacks with other images using commas, and it needs a sized element before it shows up. Angles run clockwise, 0deg up and 90deg right, so the CSS default of 180deg runs top to bottom.
Interpolate in oklch when the midpoint turns gray. Browsers blend in sRGB by default, and between complementary colors the middle goes muddy. CSS Color 4 lets you choose the interpolation space, for example linear-gradient(in oklch, red, blue), which keeps the middle vivid. Ship the plain syntax as the fallback and add the oklch version behind @supports.
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
Linear gradients at any angle from 0 to 360 degrees, and circular radial gradients from the center. Both take as many color stops as you add.
Click Add Stop to append a stop, then set its color and drag its position slider. Remove a stop with its trash icon. A gradient needs at least two stops, so the last two cannot be removed.
Yes. The output is a single background declaration using the standard linear-gradient() or radial-gradient() syntax, which every current browser reads without vendor prefixes.
Yes. Apply the gradient as background-image, then add background-clip: text (plus -webkit-background-clip: text for Safari and Chrome) and color: transparent to the element.
Random Gradient picks a new angle and two random colors, and adds a third stop in the middle about half the time. Use it as a starting point, then adjust the stops.
The color converter translates stops between HEX, RGB and HSL. The CSS formatter cleans up the rule once you paste it into your stylesheet.