Pastel gradients in CSS: palettes, hex codes and soft blends
Pastel gradient palettes with hex codes, the OKLCH numbers behind pastel, and blends that stay soft.
Updated
A pastel gradient blends colours that are very light and only a little saturated: pink, lilac, sky blue, mint, peach, butter yellow. In CSS it's one linear-gradient. Add in oklch so the blend between two pastels stays coloured instead of passing through grey:
.pastel {
background: linear-gradient(to right in oklch, #fcc5de, #ddcbf5, #b2dffa);
}That's the Cotton candy palette from the table below. Everything in the demo is plain CSS: a pastel mesh made of four radial gradients, six palettes, and one pink-to-mint blend done three ways.
import type { ReactNode } from "react";
/**
* The pastel recipes from the pastel gradient blog post, all plain CSS. Every
* colour sits near OKLCH lightness 0.85-0.95 with chroma 0.05-0.07, inside
* the sRGB gamut, so the hex codes are exact.
*/
const palettes: readonly { name: string; colors: readonly string[] }[] = [
{ name: "Cotton candy", colors: ["#fcc5de", "#ddcbf5", "#b2dffa"] },
{ name: "Peach sorbet", colors: ["#fed0b2", "#fcbfc2", "#f0bcd8"] },
{ name: "Mint and lavender", colors: ["#bdefd7", "#b7def3", "#d7c9f3"] },
{ name: "Lemon and sky", colors: ["#f6edb7", "#c6ecd6", "#b2dffa"] },
{ name: "Sea glass", colors: ["#c3f0e3", "#b5e4ed", "#becdf6"] },
{ name: "Blush and butter", colors: ["#fbefc2", "#fdd0b8", "#f8bbc3"] },
];
const blends = ["srgb", "oklab", "oklch"] as const;
const meshLayers = [
"radial-gradient(85% 95% at 16% 20%, #fcc5de, transparent 68%)",
"radial-gradient(85% 95% at 84% 26%, #ddcbf5, transparent 68%)",
"radial-gradient(85% 95% at 72% 86%, #b2dffa, transparent 68%)",
"radial-gradient(85% 95% at 22% 80%, #bdefd7, transparent 68%)",
"#fdf8f6",
].join(", ");
const label = "relative text-sm font-semibold text-neutral-900";
/**
* A box painted with `modern`, over `fallback` for browsers that drop
* gradients with an interpolation space, so no swatch ever renders empty.
*/
function Swatch({
className,
fallback,
modern,
children,
}: {
className: string;
fallback: string;
modern: string;
children: ReactNode;
}) {
return (
<div
className={`relative overflow-hidden ${className}`}
style={{ background: fallback }}
>
<div
aria-hidden
className="absolute inset-0"
style={{ background: modern }}
/>
{children}
</div>
);
}
export function PastelGradientsDemo() {
return (
<div className="grid w-full gap-3 bg-[#fdf8f6] p-4">
<div
className="flex h-48 items-end rounded-lg p-3"
style={{ background: meshLayers }}
>
<span className={label}>Pastel mesh, four radial gradients</span>
</div>
<div className="grid gap-3 sm:grid-cols-2">
{palettes.map((palette) => (
<Swatch
key={palette.name}
className="flex h-24 items-start rounded-lg p-3"
fallback={`linear-gradient(to right, ${palette.colors.join(", ")})`}
modern={`linear-gradient(to right in oklch, ${palette.colors.join(", ")})`}
>
<span className={label}>{palette.name}</span>
</Swatch>
))}
</div>
<div className="grid gap-2">
{blends.map((space) => (
<Swatch
key={space}
className="flex h-10 items-center rounded-md px-3"
fallback="linear-gradient(to right, #fcc5de, #bdefd7)"
modern={`linear-gradient(to right in ${space}, #fcc5de, #bdefd7)`}
>
<span className={label}>in {space}</span>
</Swatch>
))}
</div>
</div>
);
}
What makes a colour pastel
Pastel is high lightness with low chroma. In OKLCH, where L is lightness from 0 to 1 and C is chroma (how far the colour is from grey), pastels sit around:
- Lightness 0.85 to 0.95. Lower and the colour reads as dusty or muted. Higher and it's almost white.
- Chroma 0.05 to 0.07. Lower and it's an off-white. Much higher and it stops being pastel: saturated pink sits near 0.2.
The hue can be anything. That makes oklch() the easiest way to pick pastels by hand. Keep L and C fixed, change only the hue, and every colour comes out equally soft:
:root {
--pastel-pink: oklch(0.88 0.07 350);
--pastel-lilac: oklch(0.87 0.06 305);
--pastel-sky: oklch(0.88 0.06 235);
--pastel-mint: oklch(0.91 0.06 165);
--pastel-peach: oklch(0.89 0.066 55);
}Those five give the hex codes #fcc5de, #ddcbf5, #b2dffa, #bdefd7 and #fed0b2. Near white, the sRGB range is narrow: oklch(0.92 0.05 260), a pale periwinkle, already falls outside it, so the browser has to fit it in and the colour you get isn't exactly the one you wrote. All the palettes here stay inside sRGB, so their hex codes and OKLCH values describe the same colours.
oklch() works in Chrome and Edge 111, Firefox 113 and Safari 15.4.
Pastel palettes with hex codes
Each row is three stops, light to slightly deeper, and works in the gradient at the top of this post.
| Palette | Start | Middle | End |
|---|---|---|---|
| Cotton candy | #fcc5de | #ddcbf5 | #b2dffa |
| Peach sorbet | #fed0b2 | #fcbfc2 | #f0bcd8 |
| Mint and lavender | #bdefd7 | #b7def3 | #d7c9f3 |
| Lemon and sky | #f6edb7 | #c6ecd6 | #b2dffa |
| Sea glass | #c3f0e3 | #b5e4ed | #becdf6 |
| Blush and butter | #fbefc2 | #fdd0b8 | #f8bbc3 |
Every colour in the table has an OKLCH lightness of about 0.85 to 0.95 and a chroma of about 0.05 to 0.07, so no stop jumps out of the others. Peach sorbet, Sea glass, and Mint and lavender keep their hues close together, so they read as one soft tint. Cotton candy and Lemon and sky span more of the colour wheel and look more playful.
Why pastel gradients go grey
Pastel pairs are often near-opposite hues: pink and mint, peach and sky, butter and lavender. A plain linear-gradient blends in sRGB, which mixes the red, green and blue channels in a straight line. Between opposite hues those channels cancel out, and the middle of the gradient loses its colour.
Pink #fcc5de to mint #bdefd7 shows it. The halfway colour in sRGB is #dcdadb, a light grey with an OKLCH chroma of 0.003, against about 0.07 at both ends. OKLab, the usual fix for muddy midpoints, does no better here: its halfway colour is #e0dbdb, chroma 0.005. Both take the straight line through the middle of the colour space, where there's no colour.
in oklch blends the hue around the colour wheel instead. From pink (hue 350°) to mint (hue 164°), the shorter way round passes through orange and yellow, and the halfway colour is #f5d8ac, a soft peach with a chroma of 0.066, as pastel as the two ends. The three bars at the bottom of the demo show all three.
On a saturated gradient a grey middle looks muddy. On a pastel one it's worse: the ends are already pale, so the grey band in between looks like a dirty smudge on white.
in oklch needs Chrome or Edge 111, Safari 16.2 or Firefox 127. Older browsers drop the whole declaration, so write a plain one first:
.pastel {
background: linear-gradient(to right, #fcc5de, #ddcbf5, #b2dffa);
background: linear-gradient(to right in oklch, #fcc5de, #ddcbf5, #b2dffa);
}The middle stop is what keeps the fallback pastel. With only pink and sky blue, an sRGB blend would sag toward grey; with lilac between them, it never has far to go.
Text on a pastel gradient
Pastels are too light for white text. White on any colour in the table has a contrast ratio between 1.15:1 and 1.63:1, far under the 4.5:1 that WCAG asks for body text. Dark text is the answer:
#0f172a, a near-black navy, reaches at least 10.96:1 on every colour in the table.#4b5563(Tailwind'sgray-600) reaches at least 4.64:1, enough for body text, so secondary text can stay grey.
Hide the banding
A pastel gradient changes very little from end to end. Sea glass moves at most 35 of the 256 steps in any one 8-bit channel between its first and last colour. Stretched across a 1440px hero, that's a new step about every 41 pixels, and on a good screen those steps show as faint bands. A sunset palette from #ffd9a8 to #1d1240 moves 226 steps over the same width, so its steps are narrower and harder to see.
Grain hides the bands by breaking up the edges between steps. How to add film grain to a gradient shows an SVG noise layer in plain CSS. Ordered dithering in a shader explains the same fix inside a shader.
A pastel mesh gradient in CSS
A mesh gradient is several soft blobs of colour blending into each other. In CSS that's a stack of radial gradients over a base colour. The first one listed is drawn on top:
.pastel-mesh {
background:
radial-gradient(85% 95% at 16% 20%, #fcc5de, transparent 68%),
radial-gradient(85% 95% at 84% 26%, #ddcbf5, transparent 68%),
radial-gradient(85% 95% at 72% 86%, #b2dffa, transparent 68%),
radial-gradient(85% 95% at 22% 80%, #bdefd7, transparent 68%), #fdf8f6;
}Each blob is a colour fading to transparent by 68% of its ellipse, placed near one corner. The base #fdf8f6 is a warm off-white. Pure white behind pastels looks clinical, and a slightly warm base keeps the gaps between blobs soft. This is the same stack the free Mesh Gradient component shows before its shader starts. Mesh gradients in CSS and React shows how to animate it with @property.
Pastel gradients in Tailwind
Tailwind v4's 100 and 200 shades are pastels. In Tailwind 4.3.3, pink-200 is oklch(89.9% 0.061 343.231), purple-200 is oklch(90.2% 0.063 306.703) and sky-200 is oklch(90.1% 0.058 230.902), right in the range above. So a pastel gradient is one class list:
<div class="bg-linear-to-r/oklch from-pink-200 via-purple-200 to-sky-200"></div>The /oklch after the direction sets the blend space, and Tailwind adds the sRGB fallback itself: the compiled class sets to right, then to right in oklch inside an @supports check. Not every 200 shade is that soft: yellow-200, amber-200, emerald-200 and teal-200 have chroma between 0.093 and 0.129, so use their 100 shades for a pastel look. For hex colours from the table, use arbitrary values such as from-[#fcc5de].
Pastels in dark mode
A pastel gradient is a light-mode background. Put one behind a dark theme and it glares. There are two ways out:
- Swap the palette. Keep the hues and drop the lightness, for example to around 0.3 in OKLCH, so pink becomes a deep plum (
#442032) and sky blue a deep blue (#043247). Gradients that follow light and dark mode shows how to switch palettes with CSS variables. - Use pastels as light, not as a background. On a dark page, a pastel radial gradient at low opacity reads as a soft glow behind a heading.
A pastel gradient that moves
CSS stacks hold still unless you animate each layer. The free Mesh Gradient component draws the same four pastels as a live shader. The blobs drift and blend into each other, the motion loops seamlessly, and visitors who prefer reduced motion see one still frame:
A pastel mesh, live
import { MeshGradient } from "@/components/mesh-gradient";
// The free Mesh Gradient with the four pastels from the post's CSS mesh, on
// a warm off-white. A little grain hides the wide bands pale gradients get.
export function PastelMeshDemo() {
return (
<MeshGradient
className="flex h-[360px] items-start p-8"
background="#fdf8f6"
colors={["#fcc5de", "#ddcbf5", "#b2dffa", "#bdefd7"]}
grain={0.06}
loopSeconds={10}
>
<h2 className="text-3xl font-semibold tracking-tight text-neutral-900">
A pastel mesh, live
</h2>
</MeshGradient>
);
}
Install it with the shadcn CLI into any React project with a components.json. The free components need no account:
npx shadcn@latest add https://gradients.sh/r/mesh-gradient.jsongrain={0.06} adds just enough grain to hide the banding described above.
To tune it by eye or export it as an image or video, open this pastel mesh in the editor. Its loop is set to 10 seconds, so a free MP4 export holds one whole loop. A free account exports PNGs up to 1920px wide and 10-second MP4 loops up to 1080p60. The mesh gradient generator has more mesh palettes that open the same way.
Two free presets also sit on a pale ground: Glasswork, blue and violet light on a pale blue-grey #eef0f6, and Paper Crease, soft blue folds on warm paper with film grain. Both are a little more saturated than a true pastel.
Related
- Sunset gradients in CSS uses the same
in oklchfix for orange into indigo. - Metallic gradients in CSS places colour stops where light falls, for chrome and gold.
- Tailwind animated gradients loops any of these palettes with Tailwind classes.
- Blue gradients in CSS has seven blue palettes with hex codes, from pale sky blue to navy.
- Purple gradients in CSS has lavender and violet palettes, from pale lilac to deep purple.
- Green gradients in CSS has mint, sage and emerald palettes, from pale mint to forest green.