Palette generator

Hue and chroma anchor the middle of the ramp; the shape controls are in the inspector.

Anchor on
Token scale
--color-brand-50 … 950
Specimen

The scale in a component

Surfaces come from 50 and 100, borders from 200, body copy from 700, and the primary action from 600.

CSS variables
:root {
  --color-brand-50: oklch(0.940 0.052 325.0);
  --color-brand-100: oklch(0.907 0.071 318.7);
  --color-brand-200: oklch(0.856 0.100 312.4);
  --color-brand-300: oklch(0.787 0.139 306.9);
  --color-brand-400: oklch(0.687 0.198 301.2);
  --color-brand-500: oklch(0.591 0.256 296.5);
  --color-brand-600: oklch(0.519 0.258 293.0);
  --color-brand-700: oklch(0.440 0.239 292.8);
  --color-brand-800: oklch(0.371 0.208 291.7);
  --color-brand-900: oklch(0.301 0.171 289.9);
  --color-brand-950: oklch(0.237 0.136 287.6);
}
Anchor#7C3AED
Closest step600
Ink on 6006.36:1
900 on 5012.10:1

Color Palette Generator

Turn one brand colour into a complete token scale — eleven steps from 50 to 950 — built in OKLCH so the steps are perceptually even rather than mathematically even. Chroma and hue can be shaped across the ramp, and the output is CSS custom properties you can paste straight into a stylesheet.

Steps, 50 to 950
11
Space the ramp is built in
OKLCH
Anchor colour needed
1
Requests made
0

Step by step

How to use it

  1. 01Set the anchor

    One colour, in any CSS notation. It sets the hue and chroma the whole scale inherits, and it is the step the rest of the ramp is built around.

  2. 02Shape the ramp

    Chroma scale controls how saturated the middle of the scale stays, hue shift bends the hue gradually across it, and range decides how far the ends travel toward white and black.

  3. 03Check the ends against real use

    50 to 100 is a canvas tint, 200 to 300 are borders, 500 to 700 are primary actions, and the dark end is text. Read each step against the surface it will actually sit on.

  4. 04Copy the variables

    Output is CSS custom properties in OKLCH or hex, named from your token name — ready to paste into a stylesheet or a theme file without renaming anything.

Worked example

Why the scale is built in OKLCH

The same eleven steps, generated two ways. This is the difference between a scale that looks even and one that only measures even.

Given

Anchor
#7C3AED
Steps
50 … 950
Question
even by what measure?

Equal steps in HSL against equal steps in OKLCH

HSL lightness, evenly spaced
  the yellows and cyans wash out early
  the blues stay dark far too long
  step 400 and 500 look almost identical

OKLCH lightness, evenly spaced
  every step differs from its neighbour
  by the same perceived amount
  and the same recipe works on any hue
Steps generated
11
Even in
perception
Hue drift
yours to set

A token scale is a promise that 500 means the same thing for every colour in the system — same weight, same emphasis, same contrast behaviour. That only holds if the steps are even to the eye, which is what OKLCH gives you and HSL does not. It is also why a palette generated this way needs so little hand-correction afterwards.

Before you adopt the scale

What to know about token scales

The numbers are a contract, not decoration

500 should mean the same emphasis whether the hue is your brand purple or a warning red, so a component using primary-600 for a hover state works when the theme changes. That only holds if every scale is built the same way — which is the argument for generating them rather than picking them.

Chroma cannot stay constant across lightness

There is far more room for saturated colour in the middle of the lightness range than at either end, so a scale that holds chroma flat clips at the extremes and comes back grey or shifted. Tapering it toward the ends is why the light and dark steps look like the same colour rather than a different one.

A little hue shift makes a ramp feel natural

Shadows tend cooler and highlights warmer in the physical world, and scales that mimic that read as more considered. Keep it small — a few degrees across the whole ramp. A large shift stops being a scale of one colour and becomes two.

Check contrast at the pairs you will actually use

The useful question is not whether step 600 passes in the abstract but whether 600 on 50 passes, and whether 100 on 900 does. Those pairs are what components are built from — verify them once, and the whole system inherits the answer.

Generate, then hand-correct sparingly

A generated ramp gets you most of the way and will occasionally produce a step that is wrong for a specific use — a brand colour that must be exact, or a mid-step that clashes with an existing asset. Fix those individually, and leave the rest of the ramp generated so it stays regenerable.

Everything runs in your browser

The ramp, the contrast readouts, and the CSS output are all computed locally, and the share link carries the anchor and the shaping controls — enough for a colleague to reproduce the identical scale.

The judgement call

Which step for which job?

A scale is only useful if the team agrees what each end is for.

  • Page and card backgrounds

    50–100

    Barely tinted. Enough to separate surfaces without becoming a colour in its own right.

  • Borders, dividers, disabled fills

    200–300

    Visible against the canvas but never competing with content for attention.

  • Buttons, links, primary actions

    500–700

    The saturated middle, where there is enough contrast for white text and enough colour to read as the brand.

  • Body text on a light canvas

    800–950

    Dark enough to clear 4.5:1 comfortably while staying tinted rather than flat black.

  • A dark theme

    Invert the roles

    Do not invert the values — reassign which steps are surface and which are text, and re-check every pair.

  • One colour that must match a brand exactly

    Pin it

    Set it by hand and generate the rest around it. Do not bend the whole ramp to make the generator produce it.

Reference

How the scale is built

Steps
50 · 100 · 200 … 900 · 950Eleven stops, matching the convention most design systems and utility frameworks already use.
Space
OKLCHLightness is stepped perceptually, so neighbouring steps differ by the same visible amount at every hue.
Chroma scale
Multiplies the anchor's chromaLets the ramp stay saturated through the middle and taper toward the ends, where the gamut narrows.
Hue shift
Degrees across the rampA small drift — cooler in the shadows, warmer in the lights — reads as natural. Large shifts read as two colours.
Range
How far the ends travelControls whether 50 and 950 approach white and black or stop short of them.
Output
CSS custom propertiesOKLCH or hex, named from your token name, ready to paste into a stylesheet.

FAQ

Questions, answered plainly

How do I generate a colour palette from one colour?

Paste your brand colour as the anchor. Eleven steps from 50 to 950 are generated around it in OKLCH, inheriting its hue and chroma, and the output is CSS custom properties you can paste straight into a stylesheet.

Why 50 to 950 rather than 1 to 10?

The 50 to 950 scale is the convention most design systems and utility CSS frameworks already use, which means your tokens line up with what other tools and other engineers expect. The gaps also leave room to insert a step later without renumbering everything.

Why build the scale in OKLCH instead of HSL?

Because equal steps in HSL are not equal to the eye — yellows wash out early and blues stay dark far too long, so a scale looks uneven even though the numbers are regular. OKLCH lightness tracks perception, so one recipe produces an even ramp at any hue.

How do I know the palette is accessible?

Check the pairs you actually use rather than the steps in isolation: text steps against surface steps, typically 800 or above on 50 to 100. Once those pairs pass, every component built from the tokens inherits the result — which is the main practical benefit of having a scale at all.

Can I use this for a dark theme?

Yes, but reassign the roles rather than inverting the values. In dark mode the light steps become text and the dark steps become surfaces, and the contrast pairs need re-checking because the relationships are not symmetric.

Is anything sent to a server?

No. The ramp, the contrast readouts, and the CSS output are all computed in your browser, and the share link carries only the anchor colour and the shaping controls.

The ramp, contrast readouts, and CSS output are all computed in your browser. Share links carry only the anchor and the shaping controls.