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
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.
#6d28d9hsl(263, 70%, 50%)
⬜ 7.1 · ⬛ 3.0
#93d42dhsl(83, 66%, 50%)
⬜ 1.8 · ⬛ 11.7
#b699e2hsl(264, 56%, 74%)
⬜ 2.4 · ⬛ 8.6
#587c1fhsl(83, 60%, 30%)
⬜ 4.9 · ⬛ 4.3
#2b0d5bhsl(263, 75%, 20%)
⬜ 16.0 · ⬛ 1.3
| Text | Background | Ratio | Grade | Sample |
|---|---|---|---|---|
| #93d42d | #2b0d5b | 8.92 | AAA | Sample text |
| #2b0d5b | #93d42d | 8.92 | AAA | Sample text |
| #b699e2 | #2b0d5b | 6.59 | AA | Sample text |
| #2b0d5b | #b699e2 | 6.59 | AA | Sample text |
| #6d28d9 | #93d42d | 3.96 | AA Large | Sample text |
| #93d42d | #6d28d9 | 3.96 | AA Large | Sample text |
| #587c1f | #2b0d5b | 3.29 | AA Large | Sample text |
| #2b0d5b | #587c1f | 3.29 | AA Large | Sample 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.
: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
- Start from a colour you already have to use — a brand colour, a photograph, an existing logo.
- Pick a harmony. Analogous and monochromatic are hard to get wrong; complementary and triadic need a firmer hand.
- Lock the swatches you want to keep, then press regenerate. Locked colours pass through untouched while everything else reshuffles around them.
- Click any swatch to load its ten-step shade scale, which is what you will actually use for hovers, borders and disabled states.
- 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 |
|---|---|---|---|
| Monochromatic | One hue, varied lightness | Calm, cohesive, impossible to break | Product interfaces, dashboards, documentation |
| Analogous | Neighbours within ~60° | Harmonious with gentle variety | Editorial sites, illustration, nature themes |
| Complementary | Opposites, 180° apart | Maximum contrast, high energy | A call-to-action that must win against the brand colour |
| Split complementary | Base plus the two hues either side of its complement | Most of the contrast, far less tension | Marketing pages that need punch without shouting |
| Triadic | Three hues 120° apart | Vibrant and balanced | Playful brands, children’s products, data categories |
| Tetradic | Two complementary pairs, 90° apart | Richest and hardest to control | Illustration 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 text | 4.5:1 | Anything under 24 px, or under 19 px bold |
| AA, large text | 3:1 | 24 px and up, or 19 px bold and up |
| AA, non-text | 3:1 | Icons, form borders, focus rings, chart keys |
| AAA, normal text | 7:1 | The enhanced level; required for some public-sector work |
| AAA, large text | 4.5:1 | Headings 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.