How to Generate Random Colors Programmatically

Creating random colors is actually more difficult than it seems. The randomness itself is easy, but aesthetically pleasing randomness is more difficult. For a little project at work I needed to automatically generate multiple background colors with the following properties:

  • Text over the colored background should be easily readable
  • Colors should be very distinct
  • The number of required colors is not initially known

Naïve Approach

The first and simplest approach is to create random colors by simply using a random number between [0, 256[ for the R, G, B values. I have created a little Ruby script to generate sample HTML code:

The generated output looks like this:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

As you can see this is quite suboptimal. Some letters are hard to read because the background is too dark (B, Q, S), other colors look very similar (F, R).

Using HSV Color Space

HSV_cylinder_smallLet’s fix the too dark / too bright problem first. A convenient way to do this is to not use the RGB color space, but HSV (Hue, Saturation, Value). Here you get equally bright and colorful colors by using a fixed value for saturation and value, and just modifying the hue.

Based on the description provided by the wikipedia article on conversion from HSV to RGB I have implemented a converter:

Using the generator and fixed values for saturation and value:

returns something like this:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

Much better. The text is easily readable, and all colors have a similar brightness. Unfortunately, since we have limited us to less colors now, the difference between the randomly generated colors is even less than in the first approach.

Golden Ratio

Using just rand() to choose different values for hue does not lead to a good use of the whole color spectrum, it simply is too random.

distribution-random

Here I have generated 2, 4, 8, 16, and 32 random values and printed them all on a scale. Its easy to see that some values are very tightly packed together, which we do not want.

Lo and behold, some mathematician has discovered the Golden Ratio more than 2400 years ago. It has lots of interesting properties, but for us only one is interesting:

[…] Furthermore, it is a property of the golden ratio, Φ, that each subsequent hash value divides the interval into which it falls according to the golden ratio!
Bruno R. Preiss, P.Eng.

Using the golden ratio as the spacing, the generated values look like this:

distribution-goldenratio

Much better! The values are very evenly distributed, regardless how many values are used. Also, the algorithm for this is extremely simple. Just add 1/Φ and modulo 1 for each subsequent color.

The final result:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

You can see that the first few values are very different, and the difference decreases as more colors are added (Z and E are already quite similar). Anyways, this is good enough for me.

And because it is so beautiful, here are some more colors 😉
s=0.99, v=0.99, s=0.25, h=0.8, and s=0.3, v=0.99

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

Have fun!
Martin

31 Comments on "How to Generate Random Colors Programmatically"

Notify of

Guest
6 years 1 month ago

Nice explanation Martin! I have done something very similar in a ColorUtils for Java. I find it’s an interesting but very subjective matter and for many practical uses, you will want to seed the algorithm with avoidable colors.
I attacked the problem looking at the color space as a HSV cone, placing points as far away from another in a 3D space (and often seeding the algorithm with the color black and white).

Guest
6 years 1 month ago

I wrote a short method that given a background color will tell you whether or not white or black text will be the most readable. Using this you can still use saturated colors.

You can find it here:

http://blog.nitriq.com/BlackVsWhiteText.aspx

Guest
6 years 1 month ago

@jon, nice article with calculating white vs. black text! then you have a wider range of colors to choose from. but I have not yet thought about how to select distinct colors when you can change more than just the hue parameter.

Guest

[…] How to Generate Random Colors Programmatically | Martin Ankerl […]

Guest
Brian Harris
6 years 1 month ago

Is it safe to assume that you used the golden ratio approach instead of a perfectly even distribution because it was quicker to implement and not far from ideal anyway?

Guest
math
3 years 5 months ago

Any number that is near 0.65 and doesn’t isn’t a small integer fraction should do fine. For example:

0.673467126, which my cat just selected.

Guest
2 years 11 months ago

The requirement for the number is to make sure the values of ((n * ?) mod 1.0) do not repeat each other.
If you use any rational number, ? = A/B ((0 < A < B), then it will give you at most B different values. This is obvious – if you substitute B*x + m (0<= m < B) for n into the formula, you will get the same value regardless of the x, so the period length is B. Bottom line: if you take an irrational ?, the period length is infinity.

Now, there are infinitely many irrational numbers in the range [0, 1]; why should we care about Golden Ratio over any other (like sqrt(2))?

Because it gives us the best pairwise distance between the numbers when the count of those is not known in advance.

Guest
6 years 1 month ago

Hello Brian, no, I cannot use a perfectly even distribution because I do not know how many colors I need in advance. I simply pick colors one after the other, and do not change already picked colors. As far as I can tell the golden ratio is the optimal way for this use case.

Guest
4 years 7 months ago

what is color evenly distributed?

Guest
Konstantinos Arvanitis
3 years 10 months ago

Although it’s a long time since the article was posted, I think that Sobol sequences are a nice way to get as many colours as required without intervention and clashes.
http://en.wikipedia.org/wiki/Sobol_sequence

Guest
Konstantinos Arvanitis
3 years 10 months ago

Even easier (and what I originally had in mind) is the Halton sequence
http://en.wikipedia.org/wiki/Halton_sequence.

Guest
3 years 9 months ago

Thanks for this great resource! I’m working on a very similar problem and your approach sounds really promising.

Just to split hairs: if you need your HSV-to-RGB converter to absolutely match what Photoshop returns, you have to allow HSV values in [0..1] —including 1— and to replace …*256 by …*255. (Of course this not compliant with the fact that the rand function generates values in [0..1[ , anyway HSV is supposed to support the full [0..1] range so this can make a very slight difference in computing high values.)
@+
Marc

Guest
Brick
3 years 6 months ago

Correct the value of ?!

Guest
Brick
3 years 6 months ago

Golden ratio to 1…. instead of 0….

Guest
Guest
3 years 4 months ago

I don’t understand why you have different values for q and t above. According to the Wikipedia article you cite, they should both be v – c * ((h * 6 % 2) – 1).abs: http://en.wikipedia.org/wiki/HSL_and_HSV#Converting_to_RGB

Guest
MartinAnkerl
3 years 4 months ago

When I implemented the algorithm the article had a different description of it, and I just took it from there. I think both algorithms are the same, they first calculate R1, G1, B1 and afterwards add m to it. When you run my code with a range of numbers for h from 0 to 1, you get exactly the graph as in figure 24 on the Wikipedia page, so it should be correct

Guest
3 years 4 months ago

Ah, I understand, you have one value for when % 2 is greater than 1, and another for when it’s less.

Guest
3 years 4 months ago

I made a gem based on this blog post: https://github.com/opennorth/color-generator

Guest
MartinAnkerl
3 years 4 months ago

thats great!

Guest
3 years 4 months ago

Javascript module based on this:
https://github.com/sterlingwes/RandomColor Thanks for the inspiration! Great walkthrough

Guest
3 years 3 months ago

[…] Multi-Color SearchHow to Generate Random Colors Programmatically […]

Guest
Jess Austin
3 years 2 months ago

This is very informative; thanks for sharing.

On a recent project I did something similar, but used the new CSS functions hsl() and hsla() to make it much simpler. Basically, I have this:


var hue = 0;
Array.prototype.slice.call(document.querySelectorAll('.myClass')).forEach(function(mc) {
mc.style.color = 'hsla(' + hue + ', 75%, 50%, 0.5)';
hue += 222.5;
});

That is, hsl() and hsla() take care of normalizing the hue to the [0, 360) range for you. 222.5 is approximately 360/?. I only had to do this bit in javascript because the set of elements I’m coloring is dynamic and I didn’t want to do the work on the server, but we’re almost to the point at which we could do even this in CSS only. (come on CSS variables!) Of course, some people prefer javascript to CSS for stuff like this…

Guest

[…] also highlights a neat trick to make the random colors that were spread out nicely (idea from here). The problem is that using random to get a decimal from 0 to 1 doesn’t tend to spread the […]

Guest
1 year 6 months ago

[…] to use setStroke if you need the outline of the shape. This article has more information, including better spaced colors. Thanks to NSHipster for the random number […]

Guest

[…] very efficient unless you re-generated a different palette for another number of players. Instead, some authors recommend generating a palette using the golden ratio, taking advantage of a property resulting […]

Guest

[…] very efficient unless you re-generated a different palette for another number of players. Instead, some authors recommend generating a palette using the golden ratio, taking advantage of a property resulting […]

Guest
wpDiscuz