Skip to content
HexSlate

Color Palette Generator

#e2703a
Base AA black 6.6
oklch(0.67 0.1573 44.08)
#f0c5b3
Tint AA black 13.3
oklch(0.856 0.055 44.08)
#823100
Shade AA white 8.8
oklch(0.4225 0.1227 44.08)
#00a5ce
+180° AA black 7.3
oklch(0.67 0.1259 224.08)
#98cee3
+180° AA black 12.3
oklch(0.82 0.0629 224.08)
Some members were pulled back into sRGBThe rotation asked for a colour this gamut cannot show, so its chroma was lowered until it fits, holding the lightness and the hue exactly. The hex beside each swatch is the colour you will actually get. Lower the chroma of your base if you would rather choose where that happens.
Export
theme.css
@theme {
  --color-palette-1: oklch(0.67 0.1573 44.08);
  --color-palette-2: oklch(0.856 0.055 44.08);
  --color-palette-3: oklch(0.4225 0.1227 44.08);
  --color-palette-4: oklch(0.67 0.1259 224.08);
  --color-palette-5: oklch(0.82 0.0629 224.08);
}
base #e2703a5 swatchesrotation +180°0 locked2 clamped into sRGB

A scheme here is a fixed rotation of the base hue: 180 degrees for complementary, 120 and 240 for a triad, 150 and 210 for a split complement, with the rotations of the current scheme named in the status bar. Which wheel you rotate on decides the answer, and this one is not the wheel taught in art classes.

Where the colour wheel schemes come from

Complementary, analogous, triadic and the rest are positions on a colour wheel, and the wheel most designers picture is the red, yellow and blue one that Moses Harris printed in 1766 and Johannes Itten taught at the Bauhaus. It is a pigment model: it describes what happens when you mix paint, and its complement of red is green because red and green paint make mud.

A screen is not paint. It mixes light, so the hue 180 degrees from red is cyan, not green. This tool rotates on the perceptual wheel a screen actually has, which means a complementary pair here will sometimes not be the pair a painting textbook names. That is the correct answer for a screen, and it is worth knowing before you go looking for the green you expected.

The rotation happens in OKLCH, not HSL

Rotating hue in HSL gives you a scheme with one member that reads far darker than the others, and no amount of adjusting fixes it, because the problem is the space. HSL's L is the arithmetic midpoint of the largest and smallest RGB channel, not a lightness anybody perceives. Compare hsl(60 100% 50%) and hsl(240 100% 50%): HSL calls both 50% lightness, and their WCAG relative luminances are 0.9278 and 0.0722, a contrast ratio of 8:1 between two colours the space claims are equally light. A 120 degree triad that lands on both is not a triad, it is one bright colour and one hole.

OKLCH is built from OKLab, Björn Ottosson's 2020 fit of a perceptual colour space to the experimental data. Its L tracks what people actually see: the same yellow measures 0.968 and the same blue measures 0.452, which is roughly the gap your eye reports. Hold L and C fixed, rotate H, and every member of the scheme comes back at the same visual weight. That is the entire technical claim of this page, and it is checkable: put a triad from this tool and a triad from an HSL generator side by side and squint.

There is a catch, and it is the reason a generated colour sometimes differs slightly from the arithmetic. The sRGB gamut is not a cylinder. The maximum chroma a hue can reach varies by more than a factor of two around the wheel and changes with lightness, so a rotation that keeps L and C constant walks outside sRGB on some hues. Every member here is gamut mapped the way CSS Color 4 describes: lightness and hue are held, and chroma is bisected down until the colour fits. The naive alternative, clipping each RGB channel at 0 and 1, moves the channels by different amounts and therefore shifts the hue, which is how a vivid orange silently becomes a duller red. The status bar counts how many members needed it.

A palette is not usable until you know which text colour passes

Every swatch carries a badge naming the ink that clears WCAG 2.1 AA on it, at 4.5:1 for normal text, and the ratio it clears by. One of black or white always passes: the worst colour there is sits equidistant from both ends of the luminance range at 4.58:1. So the badge is not a pass or fail, it tells you which of the two you are committed to.

The useful part is that contrast ratio is symmetric. The formula puts the lighter colour on top whichever order you hand it the pair, so "white text is readable on this swatch" and "this swatch is readable as text on white" are the same statement with the same number. A swatch whose badge says black is therefore also a swatch you cannot use for body copy on a light page. That single fact decides most of what a palette can be used for, and it is why the badges are on the swatches rather than buried in an export.

Common problems

  • Every swatch looks like the same colour. Your base has almost no chroma. A monochromatic scheme built on a near grey is five greys, and a rotation of a grey is still that grey, because there is no hue there to rotate. Raise the chroma of the base, or use the picker and move away from the centre.
  • The light members of a monochromatic scale bunch up. A base that is already nearly white has no room above it, so the tints compress toward each other. There is no lighter version of white. Start from a mid tone and let the scale reach both ways.
  • Nothing in the palette works for text. A scheme holds lightness roughly constant on purpose, so five members at one lightness give you five backgrounds and no foreground. Take one colour into the shades and tints generator and build the ramp you need from it.
  • The Tailwind block does nothing.@theme is Tailwind v4 syntax and the block goes straight under your @import "tailwindcss"; line. A v3 project ignores the whole block and needs the colours in theme.extend.colors in tailwind.config.js instead. Check which major version your project is on before assuming the paste failed.
  • The exported colour does not match what you picked. If the swatch was gamut mapped, the hex shown is the mapped colour, not the one the rotation asked for. The hex is always the truth: it is what a browser will paint.

Frequently asked questions

How many colours should a palette have?

Fewer than this tool gives you. Five is a working set, not a finished one. Most interfaces ship one accent that carries actions and links, one supporting colour for identity, and a neutral ramp doing the rest of the work, with the semantic red, amber and green kept deliberately apart from all of it so a state never reads as branding. Treat the five here as candidates and expect to throw two away.

Why is the complement of red cyan and not green?

Because this rotates on a perceptual wheel derived from how light mixes, and 180 degrees from red on that wheel is cyan. Green is red's complement on the red, yellow and blue pigment wheel taught in art classes, which models mixing paint. Neither is wrong. If you specifically want the artist's pairing, pick the green by hand and lock it.

What does the lock actually keep?

The colour, not the slot's rule. A locked swatch stores its own hex and keeps it through every regeneration and every change of base, while unlocked slots are rebuilt from the scheme around a fresh random base. Switching schemes keeps the locks in place, so you can hold a brand colour in slot one and cycle through all six schemes around it. The locked hexes travel in the URL too.

Is the Tailwind export in OKLCH deliberate?

Yes. Tailwind's own default palette has shipped as oklch() since v4, every current browser supports the notation, and each value here is already inside sRGB so it names exactly the same pixel the hex does. The reason to prefer it is editing: nudging the first number in oklch(0.65 0.14 45) makes the colour lighter and does nothing else, while nudging a byte in a hex value changes lightness, chroma and hue at once. The CSS, SCSS and JSON exports carry hex if you would rather paste that, and the SVG is a flat swatch sheet to drop into Figma or a README.

Does any of this leave my browser?

No. The conversions, the gamut mapping, the contrast ratios and every export are computed in the page. There is no request, no account and no upload. The only thing that leaves is the URL, if you choose to share it, and it carries nothing but a base colour, a scheme name and the hexes you locked.

What can this tool not do?

It generates harmonious colour relationships. It does not know your brand, your industry's conventions, or which colours your competitors already own, and those three constraints usually decide more than harmony does. Finance and healthcare converge on blue for reasons no wheel encodes; a warning that is not somewhere near red will be misread whatever the scheme says. Use this to find relationships quickly, then check the result against the things it cannot see.