Skip to content
ColorKit

Random colors, constrained

Random color generator with bands you set

Free and with no signup, this rolls 1 to 24 colors at a time inside limits you choose: a hue arc that may wrap through red, a saturation band and a lightness band. Each set is a pure function of its seed, so the number under the controls brings the same colors back tomorrow or on a colleague's machine. Lock the swatches worth keeping and reroll only the rest, or switch on the 4.5:1 filter and every draw that would fail as body text is thrown away before you see it.

  • 100% free
  • No signup
  • Up to 24 per roll
  • Reproducible seed
  • 4.5:1 filter

Hue range

Spanning 360° of the wheel. Set From above To to wrap through red — 330° to 30° keeps you in the pinks and oranges.

Press Ctrl+V anywhere on the page to drop in a hex code and the hue range narrows to ±15° around it — no need to click the field first.

  • #33588a
    hsl(215, 46%, 37%)
  • #b43cb5
    hsl(299, 50%, 47%)
  • #79a5d1
    hsl(210, 48%, 65%)
  • #4dc2c8
    hsl(183, 53%, 54%)
  • #983837
    hsl(0, 46%, 41%)
  • #11bc18
    hsl(123, 84%, 40%)
  • #bb763e
    hsl(27, 50%, 49%)
  • #91cb20
    hsl(80, 73%, 46%)

Seed 1337 with these bands always produces this set. Change a band and the same seed produces a different one — the bands are part of the recipe, not a filter over it.

How to generate random colors worth keeping

Three moves: fence off a region of the color space, roll inside it, and keep the seed rather than a screenshot.

  1. Fence off the part of the wheel you want

    Set the hue arc first, because it decides whether the roll returns a family or a fruit salad. From 200° to 260° stays in the blues; setting From above To wraps the arc through red, so 330° to 30° covers the pinks and oranges in one span. Then narrow saturation and lightness — the defaults are 45-90% and 35-65%, which is the region where a color is strong enough to be a brand color and dark enough to carry white text.

  2. Roll, keep what works, roll again

    Press Reroll unlocked and every slot redraws. Lock the two or three worth keeping and the next reroll leaves them alone: each slot draws from its own stream, so locking slot 3 cannot shift slot 4. Turn on the 4.5:1 filter if the colors have to carry text, and any draw that fails is thrown away and redrawn up to 200 times before the slot gives up and says so.

  3. Take the colors, or take the seed

    Copy a single swatch, the whole list of hex codes, or a :root block of --random-1 to --random-N custom properties ready to paste into a stylesheet. If the set is one you might need again, copy the seed instead of the colors: that number plus the current bands reproduce exactly these swatches on any machine, which a screenshot of a palette cannot do.

Technical specifications

Colors per roll1 to 24, adjusted with the slider without disturbing anything already locked
Random sourcemulberry32, seeded — 4,294,967,296 possible seeds, and one independent stream per slot so locks never shift their neighbors
Hue controlAny arc of the 360° wheel, wrapped arcs included: 330° to 30° is a 60° span through red
Saturation and lightnessHSL bands, 0-100% each, defaulting to 45-90% saturation and 35-65% lightness
Contrast filterRejection sampling against 4.5:1 on white, on black or on either, capped at 200 draws per slot before the slot reports the band as impossible
OutputPer-swatch copy, the full hex list, or a :root block of --random-1 … --random-N custom properties
ReproducibilitySeed plus bands fully determine the set — the same pair renders the same colors on any machine, in any browser
Network useNone after the page loads: the draw runs on your CPU and no color is sent anywhere

Frequently asked questions

Why do random colors so often come out muddy or washed out?

Because unconstrained sampling spends most of its draws in the parts of the space nobody wants. Picking each of red, green and blue uniformly at random gives a mean L* of 57.5 and colors that clear 4.5:1 against white only 36.5% of the time; picking hue, saturation and lightness uniformly instead is worse in a different way — 28.4% of those draws land under chroma 10, close enough to gray that they read as a mistake. Bands are the fix: they cut out the regions where the answer was never going to be useful.

What exactly does the seed control?

The seed plus the current bands determine every swatch, so the pair is the whole recipe. The generator runs mulberry32, a 32-bit pseudo-random function, and gives each slot its own stream derived from the seed and the slot index. Change the seed and all unlocked slots redraw; change a band and the same seed produces a different set, because the bands are inputs to the draw rather than a filter applied afterwards.

Can I force every color to work with white text?

Yes — set the contrast filter to “against white text” and only colors reaching 4.5:1 survive. The mechanism is rejection sampling: draw, test, discard, repeat, up to 200 attempts per slot. If your lightness band tops out above roughly 60% the constraint is unsatisfiable and the slot will exhaust all 200 draws, which the panel reports rather than hiding — no color that pale can reach 4.5:1 against white, whatever its hue.

Does locking a swatch change the ones next to it?

No, and that is the reason each slot has a separate stream rather than all of them sharing one sequence. With a single shared stream, locking slot 3 would change how many numbers slots 4 and 5 consume and the whole tail of the palette would shuffle every time you locked something. Here slot 4 depends only on the seed and the number 4.

Two swatches came out identical — is that a bug?

It is the birthday problem, not a bug. Colors are rounded to 8-bit hex, so a narrow set of bands may leave only a few hundred distinct codes reachable, and duplicates among 24 draws become more likely than not once that reachable set drops below about 400 codes. Widening the hue arc by 20° or the lightness band by 10 points usually clears it.

Is this random enough to pick a giveaway winner or generate a token?

No. Mulberry32 is a small, fast, entirely predictable generator: anyone holding the seed can reproduce the sequence, which is exactly the property this page wants and exactly the property a draw or a token must not have. For anything where predictability matters, use crypto.getRandomValues() from the Web Crypto API instead.

How do I get random colors that still look like they belong together?

Narrow the hue arc to 30° or less and keep the saturation and lightness bands tight — that produces variation within one family rather than a set of strangers. For a set built from relationships instead of a range, start from a single color and use a harmony rule, which is what the palette generator and the color wheel do.

About randomness that produces usable color

The word random is doing two jobs in the phrase “random color generator”, and only one of them is arithmetic. Uniform sampling of the 16,777,216 sRGB codes is trivially easy and almost useless: the average draw sits at L* 57.5, a third of the space is near-neutral, and only 36.5% of draws would carry white text at 4.5:1. What people actually want is a draw from the subset of color that suits the job, which means the interesting part of the tool is not the generator but the fence around it.

The three fences here are hue, saturation and lightness because those are the axes people can reason about. Hue is the arc of the wheel you are willing to accept, and it wraps: an arc from 330° to 30° is a 60° span through red that no From-less-than-To control could express. Saturation decides whether the result reads as a color or as a tinted gray, and lightness decides whether text can sit on it. If instead of a range you want colors that stand in a fixed relationship — opposite, or 120° apart — that is a different operation, handled by the color wheel and the palette generator.

Reproducibility is the feature most random-color pages skip, and it is the one that matters once a color leaves the browser. A palette you cannot regenerate is a screenshot; a seed is a recipe you can put in a commit message. That is also why this page draws from a seeded generator rather than from Math.random, whose sequence nobody can recover. When a rolled color turns out to be a keeper, the next steps are elsewhere in the hub: the shades generator expands it into tints and shades, the Tailwind scale turns it into 50-950, the mixer blends it with a second color, and the hex code chart tells you which CSS keyword it is nearest to. A color you found in a picture rather than in a roll belongs in the image color picker instead.

Where the randomness comes from

Every number on this page is worked out by JavaScript running in the tab you are reading it in. Nothing you type, paste or open is uploaded, logged or kept, which is also why the tools carry on working after you disconnect from the network.

The seed and the locks live in the page's memory and nowhere else — no storage, no cookie, no history entry. A reload therefore starts again from seed 1337 with the default bands, so copy the seed if the set is one you will want back.