Red gradients in CSS: palettes, hex codes and blends that stay red

Red gradient palettes with hex codes, why red turns pink as it fades and maroon as it darkens, and how to blend red in CSS.

A red gradient runs from a pale blush through a strong crimson to a deep, almost black red. In CSS it's one linear-gradient. Add in oklab so the red keeps its hue as it lightens:

.red {
  background: linear-gradient(to bottom, #ffdfde, #fb666e, #c11635, #510511);
  background: linear-gradient(
    to bottom in oklab,
    #ffdfde,
    #fb666e,
    #c11635,
    #510511
  );
}

The first line is the fallback for browsers that don't support in oklab. The demo shows that palette, seven more from the table below, and three red gradients (to white, to black and to blue) in three colour spaces. Everything in it is plain CSS.

Crimson, light to dark, in oklab
Scarlet
Crimson
Rose
Brick
Maroon
Fire
Garnet
Kiln

Red #dc2626 to white

in srgb
in oklab
in oklch

Red #ff0000 to black

in srgb
in oklab
in oklch

Red #dc2626 to blue #2457e6

in srgb
in oklab
in oklch

Red palettes with hex codes

Each row works as a four-stop gradient on its own, lightest to darkest. The first five were built in OKLCH, each on one hue, with lightness stepping down and chroma peaking in the middle, then rounded to hex. Fire steps its hue from yellow-orange to red on the way down, so it's the red and orange gradient. The last two are the colours of free presets. The last column is the hue each one measures after rounding.

PaletteLightMid-lightMid-darkDarkOKLCH hue
Scarlet#ffe0d9#fb775c#c93111#56110433°
Crimson#ffdfde#fb666e#c11635#51051120°
Rose#ffdfe2#fb708c#c81753#58072110–11°
Brick#fbddd5#d78670#9c513d#47221735–37°
Maroon#e9b5b3#b95858#78292b#330a0c21–22°
Fire#fde9c1#fc9341#e72d14#67090b85–27°
Garnet#ffc2a8#ff4d7a#b0102a#0802036–44°
Kiln#ffe9c7#ff9a3a#e2340c#5c0a0279–31°

Pure #ff0000 sits at a hue of 29° in OKLCH. Below that, toward 10° to 20°, red turns cooler: crimson, then rose and raspberry. Above it, past 33°, it warms into scarlet and vermilion, and by 55° or so it's orange. Brick and Maroon are red with much of the chroma taken out. Brick is a warm red with a little over half of Scarlet's chroma. Maroon is a crimson pushed darker, starting from a dusty pink.

The presets mix hues on purpose. Garnet is crimson satin with peach and pink highlights. Kiln is the glow inside a furnace, from deep red up to cream.

Red sits in the middle

Red is the colour where white and black text come out nearly even. On pure red #ff0000, white text is 4.00:1 and black is 5.25:1, by the WCAG contrast formula. Neither is a comfortable margin, and only black passes the 4.5:1 that WCAG asks for body text.

That's because red has middling luminance. The WCAG formula weights pure red at 0.213, against 0.715 for green and 0.072 for blue. Its most vivid shade sits in the middle of the lightness range too. In OKLCH, red at 29° reaches its highest sRGB chroma at a lightness of about 0.63. Green peaks near 0.87 and blue near 0.49.

So a few steps darker or lighter decides which text colour works. The familiar web reds show it:

  • #ef4444: white 3.76:1, black 5.58:1
  • #dc2626: white 4.83:1, black 4.35:1
  • #b91c1c: white 6.47:1, black 3.25:1

#dc2626 is the first of the three where white passes.

Text on a red gradient

The palettes in the table split cleanly.

  • White text on the mid-dark stops. White reaches at least 5.34:1 on the mid-dark stops of Scarlet, Crimson, Rose, Brick, Maroon and Garnet. On Fire's #e72d14 it's 4.39:1 and on Kiln's #e2340c 4.44:1, just short. Those two lean orange, and orange is lighter than red. On every dark stop white is at least 12.96:1.
  • Black text on the mid-light stops. Black reaches at least 4.6:1 on every mid-light stop in the table, and 7.23:1 or more on all of them except Maroon and Garnet.
  • Dark text on the light stops. #0f172a, a near-black navy, reaches at least 9.97:1 on every light stop.

If a white heading has to sit across a whole red gradient, keep it over the mid-dark and dark half, or darken the light end with a scrim.

Light red is pink

At the light end, red can't stay red. In OKLCH at a lightness of 0.93, the most chroma an sRGB red at 29° can hold is about 0.036. That's why the light stops in the table look blush or peach, not red. CSS's named pink, #ffc0cb, is a light red with a little blue in it: OKLCH hue 7°, chroma 0.074.

Fading red to white shows it. Rendered in Chrome 154, here's the halfway colour of red to white, measured in OKLCH:

GradientsRGB (default)in oklabin oklch
#ff0000 → white#ff7f7f, hue 22°#ffa191, hue 30°#f9b160, hue 67°
#dc2626 → white#ed9292, hue 20°#f79f94, hue 27°#e7ac6b, hue 68°

Fading red to white, use in oklab. Pure red has a hue of 29°. sRGB puts the middle at 22°, a pink. OKLab lands on 30°, a salmon that's the same hue as the red, only lighter. in oklch should land there too, since white has no hue and the CSS spec says the other colour's hue carries through. Chrome 154 puts it at 67°, a peach-orange, 38° away. It does the same, less strongly, to blue, violet and green fades to white. White converts to OKLCH with almost no chroma and a hue of about 90°. Chrome's result matches blending toward that hue, which from red runs through orange.

If you want a light end that still reads as red rather than pink, don't fade all the way to white. Stop at a light stop that keeps some chroma, like the ones in the table.

Red to black goes through maroon

Red to black is the other common pair, and every space keeps its hue. What changes is how fast it darkens:

GradientsRGB (default)in oklabin oklch
#ff0000 → black#7f0000, L 0.37#630000, L 0.31#630000, L 0.31
#dc2626 → black#6e1313, L 0.35#540808, L 0.29#540808, L 0.29

In sRGB the midpoint of pure red and black is #7f0000, one step from CSS's named maroon, #800000. OKLab and OKLCH agree on #630000, darker. OKLab's midpoint sits at half the red's perceived lightness, so the gradient darkens at an even rate. sRGB holds onto bright red for longer, then drops off near the black end. Neither is wrong. Use in oklab for an even fade, and sRGB if you want more of the bar to read red.

Pure red to black changes only the red channel, so the gradient has at most 256 distinct colours. Across a 1440px hero, that's a new value about every 5.6px, small enough not to show on most screens. Darker reds have fewer steps. Kiln's darkest stop, #5c0a02, against its background, #060201, differs by 86 steps of 256 in red, 8 in green and 1 in blue. As a rough estimate, across 1440px the red channel changes about every 17px and the green channel only 8 times. If those edges show on a dark screen, film grain or ordered dithering breaks them up.

How red blends with other colours

Rendered in Chrome 154, here's where the halfway colour of other red gradients lands, as OKLCH chroma (0 is grey) and hue:

GradientsRGB (default)in oklabin oklch
#dc2626 → orange #f97316#ea4c1e, chroma 0.202#eb5121, chroma 0.198#ec5019, chroma 0.201
#ff0000 → yellow #ffff00#ff7f00, chroma 0.186#ffa000, chroma 0.172#ff9800, chroma 0.174
#dc2626 → blue #2457e6#803e86, chroma 0.133#8f5a93, chroma 0.106#ad2db3, chroma 0.219
#ff0000 → blue #0000ff#7f007f, lightness 0.42#8c53a2, chroma 0.133#ba00c2, chroma 0.260

Red to orange, any space works. They're neighbours on the colour wheel, and all three spaces land within a few hex steps of each other. Red to yellow passes through orange in every space. sRGB's orange is a little darker.

Red to blue, use in oklch. In sRGB, pure red to pure blue goes through #7f007f, a purple darker than both ends. OKLab lightens it but greys it into a dusty lilac. OKLCH goes round the wheel through magenta and keeps the full chroma. That's the vivid purple most people want from a red and blue gradient.

Red to green is the hardest pair. Green gradients in CSS measures it, and covers why it shouldn't carry meaning on its own. Colour vision deficiency affects about 1 in 12 men, and protanomaly makes some reds look less bright as well as greener. Don't rely on red alone to flag an error or a hot value.

in oklab and in oklch work in Chrome and Edge 111, Safari 16.2 and Firefox 127. Older browsers drop the whole declaration, which is why the example at the top writes a plain gradient first.

Red gradients in Tailwind

Tailwind v4 already blends in OKLab. In Tailwind 4.3.3, bg-linear-to-b compiles to to bottom, then to bottom in oklab inside an @supports check, so a red that stays red as it fades is one class list:

<div class="bg-linear-to-b from-red-100 via-red-500 to-red-950"></div>

For a red and blue gradient through magenta, switch to OKLCH with bg-linear-to-r/oklch, for the reasons above. For hex stops from the table, use arbitrary values such as from-[#ffdfde].

Most of Tailwind's mid reds sit just outside sRGB. Tailwind 4.3.3 defines red-600 as oklch(57.7% 0.245 27.325), and converting it to sRGB needs a green channel slightly below zero. red-400, red-700 and rose-500 are outside too. red-500 is just inside. A P3 display shows those colours as written, and an sRGB screen shows the nearest red it can, slightly duller. For a red gradient that looks the same everywhere, use hex stops like the ones in the table, which are all inside sRGB.

A red gradient that moves

A CSS gradient holds still unless you animate it. Garnet is a shader: draped crimson satin drifting slowly on a near-black red ground, one of the free presets in the Silk collection. It also answers the light-end problem above a different way: instead of fading the red toward white, it lights the folds with a separate peach #ffc2a8 and a pink #ff4d7a, so the crimson #b0102a never has to get lighter itself.

Garnet, live

Garnet installs with the shadcn CLI and no account, as components/gradients/garnet.tsx:

npx shadcn@latest add https://gradients.sh/r/c/eyJ2IjoxLCJwcmVzZXRJZCI6Imdhcm5ldCIsIm5hbWUiOiJHYXJuZXQiLCJwIjp7ImtpbmQiOiJzaWxrIiwiYmFja2dyb3VuZCI6IiMwODAyMDMiLCJibHVyIjowLjQsImNvbG9ycyI6WyIjYjAxMDJhIiwiI2ZmYzJhOCIsIiNmZjRkN2EiXSwibG9vcFNlY29uZHMiOjI4LCJzY2FsZSI6MC41NSwic2VlZCI6Miwid2FycCI6MC4zfX0.json

Animated gradient background in shadcn/ui covers placing it behind a hero and theming it. The other free reds are Kiln, a dithered furnace glow, Ember, a single red-orange arc low in the frame, and Hearth, firelight rising from the bottom edge. Garnet loops every 28 seconds, and free MP4 exports stop at 10, so set its Loop to 10 in the editor before exporting one.