paletta

How to build an OKLCH shade scale (50 to 950 in any color)

9 min read · Updated 2026-04-30 · by Andres Clavijo

An OKLCH shade scale is a sequence of colors, typically eleven steps from 50 (lightest) through 950 (darkest), that share the same hue while stepping through lightness and chroma in a perceptually predictable way. OKLCH is the right color space for this job because its lightness axis matches what your eyes actually perceive, so equal numeric steps look like equal visual steps.

If you have used Tailwind, you have used a shade scale. blue-50 through blue-950 is the canonical example. The scale is not a color picker convenience. It is the foundation of every color decision in your UI: which step pairs hit WCAG AA contrast, which step belongs in a hover state, which step works on a dark background. Get the scale right and the rest of the design system mostly takes care of itself.

This guide covers what an OKLCH shade scale is, why OKLCH is the right color space, the math behind a clean 50 to 950 scale, and how to generate one in seconds with Paletta.

Why OKLCH beats HSL and RGB for shade scales

OKLCH (defined in CSS Color Module 4) has three components: L (lightness, 0 to 1), C (chroma, 0 to roughly 0.4), and H (hue, 0 to 360 degrees). The L axis is perceptually uniform, which means an L step from 0.50 to 0.55 looks like the same brightness change whether your hue is yellow, red, or deep blue.

Neither HSL nor RGB does this. In HSL, "lightness 50%" yellow is much lighter visually than "lightness 50%" navy. In RGB, the channels do not map to lightness at all; they are additive primaries.

This matters for shade scales for one reason: you want the steps to feel evenly spaced. A user looking at your slate-300 next to slate-400 should perceive them as one step apart. If you build your scale in HSL, your dark hues will compress (steps look identical) and your light hues will expand (steps look too far apart). With OKLCH, equal-L steps look equal at any hue.

The catch is chroma. The maximum chroma your screen can display drops sharply at the lightness extremes; there is no such thing as a vivid almost-white or a vivid almost-black. Any clean shade scale has to taper chroma at both ends, which is the work of the next two sections.

The 50 to 950 convention

The 50 to 950 scale (50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 950) is a Tailwind convention that carried over from Material Design's earlier system. Eleven steps is more than most UIs need at any one time, but the redundancy is the point: it gives you spare granularity for hover states, focus rings, dividers, and the dozen other surfaces a serious design system has to handle.

A few rules of thumb that hold across most products:

  • 50 to 100: page backgrounds, subtle surfaces, almost-white tints
  • 200 to 300: borders, dividers, disabled states
  • 400: muted text, placeholder text, secondary icons
  • 500: the "true" hue, your brand color, the primary swatch
  • 600 to 700: buttons, links, primary text on light backgrounds
  • 800 to 900: headings, primary text on dark backgrounds
  • 950: deep backgrounds, modal overlays, strong contrast surfaces

The 600 to 700 range is where most product UIs put their primary text on light backgrounds, because that is where most hues hit the 4.5 to 1 threshold of a WCAG contrast checker against a 50 or 100 background. See the WCAG AA vs AAA guide for when AA is enough and when you should push to AAA.

Skip 950 if you do not need it. Some scales stop at 900, which is fine. The 950 step exists for cases where you want a near-black with a slight hue tint, which is useful for dark mode backgrounds that should not read as pure neutral.

Building a scale by hand: lightness, chroma, and hue

A clean 50 to 950 scale is three curves: a lightness curve, a chroma curve, and a hue value that stays mostly constant.

Lightness curve

The fastest path to a usable scale is a smooth interpolation from L 0.97 at step 50 down to L 0.13 at step 950. Exact endpoints do not matter much. What matters is that the curve is smooth, with no sharp kinks at any step. A sigmoid works. A tweaked linear curve also works.

Sane default values:

50  → L 0.97
100 → L 0.94
200 → L 0.86
300 → L 0.77
400 → L 0.65
500 → L 0.55
600 → L 0.46
700 → L 0.39
800 → L 0.30
900 → L 0.22
950 → L 0.13

These are starting points, not gospel. Adjust by hue and by taste.

Chroma curve

This is where most hand-built scales fall apart. Maximum chroma at any L is bounded by the display gamut, and that bound drops fast as L approaches 0 or 1. If you keep chroma constant across the scale, your 50 and 950 steps will clip; they will snap to the nearest in-gamut color and stop matching the rest of the scale.

The fix is a hump curve: low chroma at 50, peak chroma somewhere between steps 400 and 600, low chroma again at 950. The peak depends on your hue. Reds and oranges sustain high chroma at lower lightness; yellows and greens peak earlier and lose chroma fast in the dark.

Hue

Mostly, hue stays fixed. But at very dark or very light steps, holding hue constant can produce a slightly muddy result, because perceptual hue is not perfectly orthogonal to L in OKLCH. Some scales drift hue by 5 to 10 degrees at the extremes. This is a refinement, not a requirement.

If you build this by hand: start with the L values above, set H from your brand color, and tune chroma until each step looks like one step from the next. Plan for 30 minutes per scale. Plan for longer if you have eight brand colors and a neutral.

Generating a scale automatically

The hand-built path is fine for one scale. It does not scale to a real design system, where you have a primary, a secondary, an accent, an error, a warning, a success, and a neutral, each with eleven steps, plus dark mode variants.

Paletta's shade scale generator builds a complete 50 to 950 scale from a single input color in roughly two seconds. It uses the curves described above (smooth L, hump chroma, optional hue drift) and clips intelligently when the requested chroma is out of gamut.

The free tier covers single-color scale generation. Paletta Pro adds a full color system view (primary, secondary, semantic colors, neutral, all in one export), Tailwind v4 export with @theme blocks, shadcn theme files, and DTCG tokens. If you only need to generate 50 to 950 shade scales once, the free tool covers it. If you are building one per quarter, Pro pays for itself on the first export.

A note on AI generation: any tool that generates shade scales from a brand color is making opinionated decisions about chroma curves and hue drift. Paletta exposes those decisions. You can tune the L endpoints, the chroma peak, and the hue drift directly, then export the result. The defaults are sane, but they are not the only answer.

Common pitfalls

Chroma clipping at the extremes. Pick a saturated mid-tone like oklch(0.65 0.25 250) and try to apply that chroma at L 0.95. Your browser will return whatever it can, which is much less saturated than 0.25. If your scale clips at the extremes, the 50 and 950 steps will look washed out compared to the middle of the scale. Always taper chroma.

P3 versus sRGB. OKLCH supports the wider P3 gamut on modern displays. If you use chroma values above roughly 0.18 to 0.22, your color might be in-gamut on P3 but out-of-gamut on sRGB. A user on a Windows laptop will see a different color than a user on a recent MacBook. For most product UIs, cap chroma at 0.18 unless you have a specific reason to push further.

Forgetting to test contrast. The 50 to 950 scale is a tool, not a finished system. You still have to verify that the pairs you actually use (text on background) hit WCAG AA. Use Paletta's contrast checker to validate the pairs that matter for your UI before you ship.

Forgetting to test for color blindness. Two adjacent steps in a shade scale can look identical to someone with deuteranopia. The numeric distinction is real, but the perceptual distinction is not. Run your finished scale through Paletta's color blindness simulator. The full guide on designing for color blindness covers what to do when steps collapse.

Dark mode inversion. Inverting a light-mode scale to make a dark-mode scale by reversing the steps does not work. The chroma curve has to flip direction, the hue might need a small drift, and the contrast pairs are not symmetric. Generate dark mode separately. Do not invert.

Browser support and fallbacks

OKLCH is supported in all current browsers (Chrome 111+, Safari 15.4+, Firefox 113+, all current evergreen versions). For older browsers, use a feature query:

.button {
  background: #2563eb; /* sRGB fallback */
}

@supports (color: oklch(0 0 0)) {
  .button {
    background: oklch(0.55 0.22 264);
  }
}

If you are exporting from Paletta, the CSS export includes both the OKLCH value and an sRGB hex fallback for every step. The Tailwind v4 export uses OKLCH natively, since Tailwind v4 requires it. For Tailwind v3 setups, copy the hex column of the CSS export. If your starting point is a reference image instead of a brand color, you can generate a palette from a photo first, then run each extracted color through the shade scale generator.

FAQ

Why eleven steps and not nine or thirteen?

Eleven is a Tailwind convention. Material Design's older system was nine steps. Radix uses twelve. None of these is "right." Eleven gives you enough granularity for most UI states without being so dense that adjacent steps are indistinguishable.

Should the 500 step be exactly my brand color?

Not necessarily. The 500 step is a perceptual midpoint, not a brand-color slot. If your brand color is unusually dark or light, it might land closer to 400 or 600 in the scale. Pick the step that matches the L value of your brand color, then build the rest of the scale around it.

Can I use OKLCH in production today?

Yes. Browser support is universal in current versions. For users on browsers older than three years, ship an sRGB fallback. The cost of OKLCH adoption is one @supports block per declaration; the benefit is a perceptually uniform palette that works correctly at the extremes.

How do I pick a chroma peak value?

Start with 0.15 to 0.18 for most product hues. Reds, oranges, and warm hues can hold higher chroma (0.20+). Yellows and greens often need lower chroma (0.12 to 0.14) to stay in gamut. Paletta's shade scale tool auto-tunes this from your input color.

What is the difference between OKLCH and OKLAB?

OKLAB uses Cartesian coordinates (L, a, b axes) where a and b describe color opponents. OKLCH uses cylindrical coordinates (L, chroma, hue) on the same color space. They describe the same colors. OKLCH is easier to reason about for shade scales because hue stays a single number while you adjust chroma; in OKLAB you have to rotate two axes simultaneously to hold hue constant.

Try it in Paletta

Skip the math. Use the OKLCH shade scale to apply this guide in seconds.

Generate a shade scale