Build a CSS gradient
Set the stops and the geometry; the ramp above the controls is the gradient your browser will draw from the declaration below it.
How it works
A gradient is a list of colours plus a rule for the space between them. The rule is the part nobody reads. An engine walks the gradient line and, at each point along it, mixes the two surrounding stops channel by channel in whatever colour space the declaration names. Change the space and every pixel between the stops moves while the stops themselves stay exactly where they were.
The middle of a gradient is a colour nobody chose
sRGB is the default, and it averages the gamma-encoded bytes rather than the light those bytes stand for. Blue #0000ff to yellow #ffff00 has a midpoint of exactly #808080: OKLCH chroma 0.000, from ends carrying 0.313 and 0.211. Pure red to pure green lands on #808000, an olive at OKLab lightness 58.1, which is darker than the red end at 62.8 and nowhere near the green at 86.6. That dip is the dark bar people keep finding across the centre of a wide banner.
Naming an interpolation space changes the path rather than the endpoints. The same red-to-green midpoint under `in oklab` is #d0a800 at lightness 74.6, sitting between its ends instead of below both. The chroma story is less tidy: for hues on the same side of the wheel the sRGB midpoint sometimes carries more chroma, not less. This page measures both midpoints from the first pair of stops you enter, so the trade is two hex values on the page rather than an assertion about colour science.
0deg points up, and 45deg is the trap
The CSS Images specification defines the gradient angle as clockwise from straight up: 0deg runs bottom to top, 90deg runs left to right. Trigonometry, canvas arcs and most drawing tools measure anticlockwise from the positive x axis. Converting between the two conventions is a reflection, css = 90 minus maths, and the fixed point of that reflection is 45. A diagonal handed over at 45 degrees therefore arrives correct, every other angle arrives mirrored, and the bug survives the one test somebody ran. SVG sidesteps the argument by taking two coordinates instead of an angle.
Corner keywords are not shorthand for a diagonal angle either. `to bottom right` is defined so the gradient line is perpendicular to the line joining the other two corners, which puts a 50% stop exactly on them and makes the angle a function of the box. On an 800 by 100 banner that computes to 172.9deg, near enough straight down. Written as `135deg` the same banner gets a true 135deg. The keyword and the angle agree only when the box is square.
The same declaration covers a different distance in every box
The gradient line's length follows from that construction: abs(W times sin A) plus abs(H times cos A). At 45deg an 800 by 100 box gives 636.4px of line; a 320 by 240 box gives 396.0px. A stop at 50% lands 318.2px along the first and 198.0px along the second, so a component reused at two sizes changes its own proportions and a soft edge tuned in the wide instance turns abrupt in the narrow one. A percentage is a fraction of the line; a stop written in px is an absolute distance along it.
A hard stop is two stops sharing one position, not a feature with a name. The toggle here puts the boundary halfway between each pair and writes the colour twice at that percentage, so the interval available for mixing has zero length and the colour changes between one pixel and the next. Repeating gradients are the same trick wearing a hat: the cycle length is the last stop's position, so a list ending at 100% completes one cycle and looks identical to the non-repeating version.
Why a subtle gradient bands harder than a bold one
Each channel of the frame buffer holds 256 values, so a ramp between two colours twelve levels apart has at most thirteen distinct steps to spend however wide the box is. Stretched across 1600px each step is 133px of flat colour with a visible edge at each end. Black to white across the same width gets 255 steps at 6.3px, which reads as smooth. Low contrast over a long distance is the case that bands, and it is the case a page background is always made of.
Interpolating in OKLab does not fix banding, because the buffer is still eight bits per channel whatever space the mixing happened in. Dithering does: a faint noise layer over the gradient scatters the boundary so no continuous edge survives for the visual system to find. The finding is a real mechanism rather than a metaphor, described by Ernst Mach in 1865, and it is why a one-level step invisible inside a photograph is obvious in a ramp.
Questions
Why does my blue to yellow gradient go grey in the middle?
Because the midpoint of a per-channel average between two near-opposite hues is grey, and in this case exactly grey: #0000ff and #ffff00 average to #808080, chroma 0.000. Nothing is wrong with the browser. Either add a middle stop naming the colour you want the transition to pass through, or mix in a space where the path bends, which is what the interpolation control writes into the declaration.
What happens in a browser that does not know in oklab?
An unrecognised token makes the whole value invalid, and an invalid declaration is dropped at parse time, so nothing paints rather than falling back to sRGB. The cascade is the fallback: write the plain version first and the oklab version on the following line, and an old engine keeps the first while a current one takes the second.
What does the hard stop toggle actually emit?
For each adjacent pair it puts a boundary at the midpoint of their two positions and writes both colours at that same percentage. Two stops at one position leave no distance to interpolate over, so the change happens in a single pixel step. Turning it on grows the stop list by roughly one line per stop, and the resolved list below the declaration shows the result.
Why does my repeating gradient only draw one cycle?
The cycle is the distance from the first stop to the last, so a list running 0% to 100% has a cycle as long as the gradient line and repeats once. Move the last stop in to 20% and the same list tiles five times. This is also why a repeating gradient with a smooth ramp shows a hard seam: the last colour meets the first one again with no transition between them.
Can I download the ramp as an image?
No, deliberately. The only way to draw a gradient into a bitmap in a browser tab is a 2D canvas, whose gradients interpolate in sRGB and offer no other option, so a PNG of an oklab ramp would not match the swatch above it or the page you paste the CSS into. The declaration is the artifact worth taking.