Skip to content

Colour palette generator with contrast checking

Build harmonious palettes from any base colour — complementary, analogous, triadic and more — with shade scales, WCAG contrast pairs and CSS export.

  • Runs in your browser
  • Nothing you enter is sent
  • Free, no account
Base colour and harmony
Harmony

Two hues opposite each other on the wheel. The highest possible contrast between colours, which is why it is the default for a call-to-action against a brand colour — and why it looks shouty if you use both at full saturation.

Palette
Lock a swatch to keep it while the rest reshuffle. Click a swatch to load its shade scale below.
#6d28d9

hsl(263, 70%, 50%)

⬜ 7.1 · ⬛ 3.0

#93d42d

hsl(83, 66%, 50%)

⬜ 1.8 · ⬛ 11.7

#b699e2

hsl(264, 56%, 74%)

⬜ 2.4 · ⬛ 8.6

#587c1f

hsl(83, 60%, 30%)

⬜ 4.9 · ⬛ 4.3

#2b0d5b

hsl(263, 75%, 20%)

⬜ 16.0 · ⬛ 1.3

Shades and tints — violet
A ten-step scale at fixed lightness values, the way design systems normally name them. Handy for hover states, borders and disabled text.
50
#f4f0fa
100
#e6dcf4
200
#cab1f1
300
#aa81e9
400
#8952e0
500
#6c26d9
600
#5b20b6
700
#47198f
800
#341268
900
#200b41
Contrast pairs
Every combination of two palette colours as text on background, graded against WCAG 2.1. 4.5:1 passes AA for body text, 3:1 for large text and interface elements.
TextBackgroundRatioGradeSample
#93d42d#2b0d5b8.92AAASample text
#2b0d5b#93d42d8.92AAASample text
#b699e2#2b0d5b6.59AASample text
#2b0d5b#b699e26.59AASample text
#6d28d9#93d42d3.96AA LargeSample text
#93d42d#6d28d93.96AA LargeSample text
#587c1f#2b0d5b3.29AA LargeSample text
#2b0d5b#587c1f3.29AA LargeSample text

Only pairs reaching 3:1 are listed. If nothing appears, the palette is too uniform in lightness to use one colour on another — pair the swatches with white or near-black instead.

Export
:root {
  --color-violet: #6d28d9;
  --color-lime: #93d42d;
  --color-violet-2: #b699e2;
  --color-lime-2: #587c1f;
  --color-violet-3: #2b0d5b;

  /* violet scale */
  --color-violet-50: #f4f0fa;
  --color-violet-100: #e6dcf4;
  --color-violet-200: #cab1f1;
  --color-violet-300: #aa81e9;
  --color-violet-400: #8952e0;
  --color-violet-500: #6c26d9;
  --color-violet-600: #5b20b6;
  --color-violet-700: #47198f;
  --color-violet-800: #341268;
  --color-violet-900: #200b41;
}

How to build a palette

  1. Start from a colour you already have to use — a brand colour, a photograph, an existing logo.
  2. Pick a harmony. Analogous and monochromatic are hard to get wrong; complementary and triadic need a firmer hand.
  3. Lock the swatches you want to keep, then press regenerate. Locked colours pass through untouched while everything else reshuffles around them.
  4. Click any swatch to load its ten-step shade scale, which is what you will actually use for hovers, borders and disabled states.
  5. Check the contrast table before you commit, then export CSS variables, a Tailwind config or JSON.

The six harmonies

Harmony Hue relationship Character Good for
MonochromaticOne hue, varied lightnessCalm, cohesive, impossible to breakProduct interfaces, dashboards, documentation
AnalogousNeighbours within ~60°Harmonious with gentle varietyEditorial sites, illustration, nature themes
ComplementaryOpposites, 180° apartMaximum contrast, high energyA call-to-action that must win against the brand colour
Split complementaryBase plus the two hues either side of its complementMost of the contrast, far less tensionMarketing pages that need punch without shouting
TriadicThree hues 120° apartVibrant and balancedPlayful brands, children’s products, data categories
TetradicTwo complementary pairs, 90° apartRichest and hardest to controlIllustration and packaging, rarely UI

Whichever you choose, the 60-30-10 rule still governs the result: about 60% of the surface in a dominant neutral or light tint, 30% in a secondary colour, and 10% in the accent. Palettes fail far more often from being used in equal measure than from having the wrong hues in them.

Reading the contrast table

WCAG contrast is the ratio between the relative luminance of two colours, running from 1:1 (identical) to 21:1 (pure black on pure white). The thresholds that matter:

Requirement Ratio Applies to
AA, normal text4.5:1Anything under 24 px, or under 19 px bold
AA, large text3:124 px and up, or 19 px bold and up
AA, non-text3:1Icons, form borders, focus rings, chart keys
AAA, normal text7:1The enhanced level; required for some public-sector work
AAA, large text4.5:1Headings under the enhanced level

Two things the ratio does not capture. First, it says nothing about colour blindness: red and green of identical luminance pass the check and are indistinguishable to roughly 8% of men, so never carry meaning in hue alone. Second, it is a luminance formula, not a perception model — saturated blues in particular often measure worse than they read. Use the number as a floor, not as a design decision.

How the shade scale is built

Each step keeps the hue and saturation of the base colour and moves to a fixed lightness: 96% at step 50, down through 50% at step 500, to 15% at step 900. That is the approach Tailwind and most design systems take, and it has two useful properties. Steps stay recognisably the same colour, and the same step number lands at a predictable contrast level across every hue in your palette — so brand-700 on brand-50 works whichever brand colour you swap in.

In practice you will use the extremes far more than the middle: 50 and 100 for surfaces and hover states, 600 and 700 for text and solid buttons, 900 for headings on a tinted background. The 400–500 range is usually too light for text and too dark for a background.

From palette to design tokens

A palette becomes usable when the colours get semantic names. Export the hex values, then map them once:

:root {
  /* raw palette */
  --violet-600: #6d28d9;
  --violet-50:  #f5f3ff;

  /* semantic tokens — what components actually reference */
  --color-primary: var(--violet-600);
  --color-surface: var(--violet-50);
  --color-on-primary: #ffffff;
}

Components should reference --color-primary, never --violet-600. That one indirection is what lets you rebrand, add a dark theme, or run a high-contrast mode without touching a single component.

Everything is computed locally

Hue rotation, the shade scale, the luminance maths and every export run in this tab. There is no account, no saved palette on someone else’s server, and no limit on how many times you can press regenerate. Unreleased brand colours stay on your machine.

Questions

Which harmony should I start from?

Analogous or monochromatic if you want calm and cannot go wrong. Complementary when one colour has to fight for attention against another, as with a call-to-action. Triadic and tetradic look great in a mood board and are hard to control in a real interface — mute all but one of the hues.

What does the contrast table actually measure?

The WCAG 2.1 relative luminance ratio between two colours, from 1:1 to 21:1. Body text needs 4.5:1, text above 24 px or bold above 19 px needs 3:1, and interface components such as focus rings and icons need 3:1 against their surroundings.

Why does the palette change when I press regenerate?

Unlocked swatches are recomputed from the harmony formula with a fresh random base hue and a small wobble. Lock the swatches you want to keep — a locked colour is passed through untouched, so you can fix a brand colour and shuffle everything around it.

How is the shade scale calculated?

Each step keeps the hue and saturation and moves to a fixed lightness — 96% for step 50 down to 15% for step 900 — the same approach Tailwind and most design systems use. That produces steps that stay recognisably the same colour and land at predictable contrast levels.

Can I export straight into my project?

Yes. The export tab gives CSS custom properties, a Tailwind colour object for both v3 config and v4 @theme, and JSON with the hex, RGB, HSL and contrast values for every swatch.