What a CSS gradient does between the stops
A CSS gradient looks like a special effect and is really a very small piece of arithmetic applied along a line. Knowing the arithmetic explains the two things that most often go wrong with gradients: the dead grey band in the middle of some of them, and the fact that moving a stop does something different from what people expect.
Interpolation, one channel at a time
A two-stop linear gradient draws a line across the box, puts the first colour at one end and the second at the other, and fills everything between by interpolating. For a point a fraction t of the way along, where t runs from 0 at the first stop to 1 at the second, each channel is computed independently:
value = start + (end − start) × t
That is the whole mechanism, done three times. Take the tool's defaults, #4ade80 (which is 74, 222, 128) to #38bdf8 (which is 56, 189, 248), and ask what sits a quarter of the way along:
- Red:
74 + (56 − 74) × 0.25 = 69.5 - Green:
222 + (189 − 222) × 0.25 = 213.75 - Blue:
128 + (248 − 128) × 0.25 = 158
Three independent straight lines. By default the interpolation happens in sRGB, on the same gamma-encoded bytes the hex code stores, which is worth remembering when the result looks off.
Why some gradients go grey in the middle
Here is the case that catches people. Consider two colours whose channels are exact opposites — each channel in one is 255 minus the matching channel in the other. #ff0000 and #00ffff are a clean example: red is 255, 0, 0 and cyan is 0, 255, 255.
At the halfway point t is 0.5, so every channel lands on the average of its two ends. Red averages to 127.5. Green averages to 127.5. Blue averages to 127.5. All three channels equal means no channel dominates, and a colour with three equal channels is grey by definition. This is not a quirk of red and cyan; it happens for every pair whose channels sum to 255, which is what "opposite" means in RGB terms.
And the grey is darker than you would guess. Mid-grey #808080 has a relative luminance of 0.2159. The two endpoints have luminances of 0.2126 and 0.7874, which average to 0.5. So the midpoint of the gradient carries well under half the light of the average of its ends — a visible dip in brightness right where the eye spends most of its time. That combination, no hue and low light, is the dead band.
The fix is not a setting, it is a third stop. Pick a colour that lies off the straight line between the two — something with a hue between them rather than none — drop it in the middle, and the path bends around the neutral axis instead of through it.
What the angle means
The angle sets the direction of that line. 0deg points straight up, and the angle increases clockwise, so 90deg points right and 180deg points down. The default 135deg therefore runs toward the bottom-right, which is why it reads as a diagonal from the top-left corner. The browser sizes the line so the first and last stops land exactly on the corners of the box, which means the same declaration produces a different-looking gradient in a wide box than in a tall one.
Stop placement
With two stops and no positions given, the first sits at 0% and the second at 100%, and the transition uses the whole line. Add a position and you change how much of the line the transition gets, not where the colours are:
#4ade80 30%as the first stop means the first 30% of the line is flat, unmixed green, and the entire transition is compressed into the remaining 70%.- Two positions close together, say
40%and60%, give you two large flat fields with a narrow band of blending between them. - Stops at
0%and50%put the second colour at halfway and hold it flat for the rest of the box.
A gradient that looks like a hard edge and one that looks like a soft wash can have identical colours; the only difference is how much of the line the interpolation is allowed to use.
What the builder outputs
The free CSS Gradient builder takes two colours and an angle and returns one line: background: linear-gradient(135deg, #4ade80, #38bdf8);. Two stops, no positions, and no colour-space keyword — so the browser interpolates in sRGB, exactly as described above.
That is deliberately the simple case, and it is also a complete, valid declaration you can extend by hand. Adding percentages after the colours, inserting a third stop to steer around the grey, or swapping linear-gradient for radial-gradient are all edits to the string it hands you. The builder gets the syntax right; the shape of the thing is yours.