Random Color Generator

Random colours drawn in HSL with the hues spread around the wheel, each one with its contrast against black and white, so the set is usable rather than mud.

Live output

Enable JavaScript to customise; default output below.

Sets the saturation and lightness bands. "any" is uniform random, which is mostly mud, and it is there so you can see why the bands exist.

The hues are spread evenly and then wobbled by up to this much. At 0 the spacing is exact; at 180 it is effectively random.

Live preview colors.txt
Waiting for your browser

Colours are drawn from crypto.getRandomValues when the page loads, so
they are yours rather than the build's. Until then this is the
placeholder, #1e56ec.

Output is valid and updates as you type.

Three random bytes give you a uniform point in the RGB cube, and most of that cube is mud. The results cluster near the greys because that is where the volume is, half of them are too dark to put text on and too light to read against, and a set of six has no relationship to each other at all.

So the randomness here happens in HSL. The hue is free, the saturation and lightness stay inside a band you choose, and the hues are spread evenly around the wheel from a random starting point rather than drawn independently. That is what makes a set look like a family instead of a screenshot of a random number generator.

Every colour arrives with its contrast against black and against white, and the tool names which text colour to use.

How to use

  1. Pick a range: vivid, pastel, muted, dark, light, or custom.
  2. Choose how many colours and how much hue jitter you want.
  3. Copy the hex values or the custom property block.

Example

Five vivid colours, hues 72 degrees apart with a 12 degree wobble:

Mood     vivid (saturation 70-100%, lightness 45-60%)
Hues     5 spread 72.0° apart, ±12°

#47c5e7  rgb(71 197 231)  ·  oklch(76.8% 0.118 219.5)
  white text 2.02:1, black text 10.41:1 — use black text, AAA
#920ee7  rgb(146 14 231)  ·  oklch(53.3% 0.272 304.3)
  white text 6.11:1, black text 3.44:1 — use white text, AA only
#c82351  rgb(200 35 81)  ·  oklch(54.6% 0.198 11.9)
  white text 5.50:1, black text 3.82:1 — use white text, AA only
#d4e529  rgb(212 229 41)  ·  oklch(88.0% 0.191 115.2)
  white text 1.40:1, black text 15.04:1 — use black text, AAA
#1edb56  rgb(30 219 86)  ·  oklch(77.9% 0.225 147.0)
  white text 1.85:1, black text 11.32:1 — use black text, AAA

Yours will differ: the colours are drawn when the page loads.

One fact worth taking away from that table: every colour carries either black or white text at the AA threshold, and that is arithmetic rather than luck. The ratio against white falls as a colour darkens and the ratio against black rises, and the two cross at 4.58:1. The better of them can never be below 4.5. The useful question is not whether a colour can hold text, it is which text, and whether it reaches 7:1 for AAA.

Pitfalls

Uniform random RGB is not a palette. It is not even a set of usable colours. The bands exist because the useful part of the space is a thin slice of it, and the “any” option is included so you can see what happens without them.

Independent random hues clump. Six uniform draws will usually put three colours in one quarter of the wheel and leave a gap opposite. Spreading the hues and randomising only the starting point gives you a set that covers the wheel, which is what a palette needs.

Equal lightness in HSL is not equal lightness to the eye. hsl(60 100% 50%) is yellow and looks bright; hsl(240 100% 50%) is blue and looks nearly black. Both are 50 percent lightness. That is why the oklch value is printed too: in oklch the lightness number means what it says across hues.

Contrast is against a background, not a property of a colour. The two ratios here are against black and white, which is the common case. If your background is a mid grey, neither figure applies, and the contrast checker on this site is the tool for it.

AA is a floor, not a target. 4.5:1 is the minimum for body copy, and copy set at exactly 4.5 is legible rather than comfortable. AAA is 7:1, and the tool says which colours reach it.

Random is a starting point. A generated set gives you somewhere to begin. A brand palette needs a decision about what the colours mean, which needs a person.

Compatibility

Randomness comes from crypto.getRandomValues, and the page recomputes on load, so what you see is yours. At build time there is no randomness, so the default output says it is waiting for your browser rather than baking a colour into a page every visitor would see.

Contrast ratios are the WCAG 2 formula on relative luminance, which is the one that conformance is measured against. It has known weaknesses, particularly for dark backgrounds, and APCA is the proposed replacement in WCAG 3; until that lands, this is the number that counts.

Values are sRGB, which is what a hex code means. oklch is printed alongside because it is the space to edit a colour in, and it is in every current browser: oklch() has been supported since 2023, so you can paste those values straight into CSS.

Frequently asked questions

Can I get a palette rather than a set of random colours?
This is closer to a palette than uniform random, because the hues are spread and the bands are held. For a full UI palette with surfaces, text and states worked out from one brand colour, use the UI colour palette generator on this site.
What do the mood names mean?
They are saturation and lightness bands. Vivid is high saturation at mid lightness, pastel is high lightness with moderate saturation, muted is low saturation, dark and light are what they sound like. Custom lets you set the bands yourself.
Why is the jitter useful?
Exactly even hues can look mechanical, particularly at four or six colours where they land on the primaries. A few degrees of wobble keeps the spread and loses the regularity.
Should I use these for a chart?
With care. A chart needs colours that are distinguishable by people with colour vision deficiency, which even spacing does not guarantee: red and green sit opposite each other on the wheel and are the classic confusion. Check the set with a simulator.
How do I get one colour rather than a set?
Set the count to one. The hue is then a single random draw and the contrast figures still apply.
Weekly drops

New tools, when there are new tools

One email when something worth using ships. No schedule to fill, so no filler.

Your address goes nowhere else, and one click unsubscribes.