CSS gradient generator — linear, radial and conic, with the muddy middle explained
Build a gradient with as many colour stops as you need, drag them along the bar, and copy a background-image rule you can paste straight into a stylesheet. Linear takes an angle or a corner keyword, radial takes a shape, a size and a centre, and conic takes a starting angle — the three of them cover every gradient CSS can draw. The page also prints the colour sitting exactly halfway between your first two stops, because that midpoint is where a gradient usually goes wrong and nothing else tells you what it is.
- Nothing is uploaded or saved
- Works offline
0deg points to the top and the angle grows clockwise, so 90deg is “to right”.
Repeating restarts the stop list past the last stop, so it only shows when the last stop sits below 100%.
.hero {
background-image: linear-gradient(135deg, #8b7cff 0%, #79d6c8 100%);
}Halfway between #8b7cff and #79d6c8, a CSS gradient paints #82a9e4 — the plain average of the sRGB bytes.
Working on the same colours elsewhere: convert a colour between HEX, RGB, HSL and OKLCH, check text contrast over a flat colour and build a layered box-shadow.
How it works
- 1
Choose linear, radial or conic
Linear runs along a straight line across the box. Radial spreads out from a point in rings. Conic sweeps around a point like the hand of a clock, which is what makes pie charts and colour wheels possible with no image and no SVG. Switching between them keeps your stops, so you can see the same colours as three different gradients in three clicks.
- 2
Aim it — by angle, or by corner
For a linear gradient the direction is either a number of degrees or a keyword like “to bottom right”. They are not interchangeable: an angle is fixed, while a corner keyword is worked out from the shape of the box every time it is drawn. Pick a keyword, then flip the preview between wide, square and tall and watch the direction move while the CSS stays identical.
- 3
Add stops where you want them
Click anywhere on the bar under the preview to drop a stop there, already holding the colour that was at that point. Drag any stop to move it, or nudge a focused one with the arrow keys. Each stop then gets a colour picker and an opacity slider of its own in the panel underneath — transparency is a separate control because no browser colour picker offers it.
- 4
Read the midpoint before you commit
Under the CSS you will find the exact colour halfway between the first two stops. That is not an opinion about your palette: a default CSS gradient blends in sRGB, so the halfway colour is the plain average of the two sets of bytes, and this page does that arithmetic for you. When the answer comes back a near-neutral grey between two strong colours, that grey is what a third of your gradient is going to look like.
- 5
Copy the rule
The output is a full declaration on background-image with a selector around it, so it drops into an existing file without being reformatted. Change the selector in your editor; nothing else needs touching. The gradient is generated by this page as you edit and nothing about it is stored or sent anywhere.
Frequently asked questions
Why does my blue-to-yellow gradient have a grey band through the middle?
Because a CSS gradient, by default, blends in sRGB by averaging the red, green and blue bytes of the two colours. Take blue (#0000ff) and yellow (#ffff00): red averages 0 and 255 to 128, green averages 0 and 255 to 128, blue averages 255 and 0 to 128. The midpoint is #808080 — a perfectly neutral grey, with no trace of either colour left in it. Load the “Blue to yellow” preset above and the tool prints exactly that. It happens whenever two colours sit on opposite sides of the colour wheel, and it is the single most common reason a gradient built from two nice colours looks dirty in the middle.
How do I avoid it?
Three ways, in order of how much they change. The cheapest is to add a third stop in the middle by hand and pick a colour that actually belongs in the transition — a green or a teal between blue and yellow — which turns one long muddy blend into two short clean ones. The second is to pick two colours that are closer together on the wheel in the first place; a hue shift of thirty or forty degrees never produces a grey midpoint because the average of two similar hues is still that hue. The third is to ask for a different interpolation space: CSS defines interpolation hints such as `linear-gradient(in oklab, …)` and `in oklch`, which blend through a perceptual space instead of raw sRGB bytes and keep the chroma up through the middle. Check current support for that syntax against your own browser targets before you rely on it — this page does not make a support claim it cannot show you.
Which way does linear-gradient(45deg, …) actually point?
Up and to the right. CSS gradient angles start at 0deg pointing to the top of the box and increase clockwise, so 90deg is to the right, 180deg is to the bottom and 270deg is to the left. That is a different convention from the one in trigonometry, where angles start at the right and increase anticlockwise, and it is why a gradient built from a remembered formula so often comes out rotated by ninety degrees. The angle names the direction the gradient travels towards, not the side it starts from.
Is “to bottom right” the same as 135deg?
Only on a square. A corner keyword is not shorthand for an angle — the specification says the gradient line must be angled so that a line perpendicular to it passes through the two neighbouring corners. On a square that works out to 135deg for “to bottom right”, but on any other shape it is a different angle, and it changes again if the box is resized. The practical consequence is worth remembering: a keyword gradient on a responsive element keeps both untouched corners the same colour at every width, while a fixed angle does not. Select a keyword above and switch the preview between wide, square and tall to watch it happen.
My gradient looks stepped, with visible stripes. Is that the gradient or my screen?
Almost always the screen, and it is arithmetic rather than a bug. Each channel has 256 possible values on an ordinary display. A gradient that runs from black to white across 1,000 pixels has to spread 256 steps over 1,000 pixels, so the same value repeats for roughly four pixels in a row and then jumps — and on a large flat area, at low contrast, the eye picks that jump out as a band. Long, slow, low-contrast ramps show it most; short or high-contrast ones almost never do. Adding a faint noise texture over the top is the usual fix, because breaking the boundary up is easier than adding colours that do not exist.
How do I make hard stripes instead of a blend?
Give two stops the same position. A transition of zero length is a hard edge, so `#000 0%, #000 10%, #fff 10%, #fff 20%` draws two solid bands with no blending at all, and wrapping that in repeating-linear-gradient tiles it across the whole box. The “Hard stripes” and “Conic pie slices” presets above are both built this way. The generator counts these for you and reports them as hard edges rather than treating them as an error, because they are a technique, not a mistake — and it never reorders your stops, since sorting them would silently destroy the effect.
Why does my repeating gradient show nothing but a solid blend?
Because the last stop is at 100%. A repeating gradient tiles the stop list past its final stop, so if that stop already sits at the far end of the gradient line there is nothing left to repeat into and it renders exactly like the non-repeating version. Move the last stop down to 20% or 30% and the pattern appears immediately. The same rule applies to repeating-radial-gradient and repeating-conic-gradient.
Can I animate a gradient?
Not by transitioning the gradient itself. Browsers do not interpolate one gradient image into another, so a transition on background-image jumps from the old value to the new one at the end of the duration rather than blending through. The two things that do work are animating background-position across a gradient made larger than its box, which slides the colours through the visible area, and stacking two elements with different gradients and cross-fading their opacity. Both animate a property that browsers really do interpolate, which is why they are smooth and a direct swap is not.
Should this go on background or background-image?
This page emits background-image, and that is the safer of the two. The `background` shorthand resets every background property you have not mentioned — including background-color, which is what shows through the transparent parts of a gradient and what a browser paints if the gradient is not understood. Setting background-image leaves your existing background-color alone, so a semi-transparent gradient still has something behind it. If you want a solid fallback colour, declare background-color first and the gradient after it.
Is a CSS gradient better than exporting a JPEG or PNG?
For a flat blend, nearly always. A gradient is a few dozen bytes of text inside a stylesheet you were already loading, it costs no extra request, it stays sharp at every size and every pixel density, and it can be recoloured by changing one value. An exported image is a separate file at a fixed resolution that has to be re-exported to change anything, and — being an 8-bit image — is more likely to band than the live gradient is, not less. The case for an image is when the effect is not really a gradient at all: grain, painted texture, photographic light. Those are pictures, and CSS should not be asked to draw them.