Secrets of the Golden Angle, and unique colour generation 🌈

Using a neat bit of maths, we can generate an infinite list of unique contrasting colours.
A lorikeet sitting in some colourful plants.
Make your designs or websites as colourful as this gorgeous lorikeet — photo by Chris Charles

Need to spruce up a website or graph with some colour, but don’t know ahead of time how many elements you need to display? It turns out that picking unique contrasting colours for each element is pretty easy.

By multiplying the golden angle, 137°, by the index of our element, we get strongly contrasting colours with no repeats. Here’s some example code:

In case the JSFiddle below does not work, here you can see the generated colours. Note this starts at hue 0°, red, and then goes through the colours described above.

We’re providing a background colour to our HTML elements using hslHue, Saturation, Luminosity (Lightness). Saturation and Luminosity are both percentages, whereas Hue is an angle from 0 to 360 degrees. If you’ve not come across these before, think back to the colour picker in MS Paint.

Hue being an angle makes sense if you think of colour in terms of a colour wheel — with red at the top at 0°, green at the bottom right at 120°, and blue at the bottom left at 240°.

Treating hue as an angle allows us to take advantage of a curious property known as the Golden Angle: 137.507…° (We’ll call it 137° for simplicity though!)

The Golden Angle 👑

The Golden Angle, where b is 137°. Sourced from https://en.wikipedia.org/wiki/Golden_angle

This angle, when added to itself, will generate unique but equally spaces values around a circle. Note we’ll mod the values by 360 each time so we have a useful value. Remember that the modulo operation is the same as clock math. These angles will correspond nicely to a contrasting set of colours.

Here we can see how incrementing the angle 137 creates nicely varying output hues.

This will continue to produce colours unlike the previous one, uniquely generating up to 360 distinct values before starting again. You can see the result of this series in the image.

If it’s unclear why you need a value like 137°, instead of a randomly picked one — consider if you’d picked a number close to 90° as your offset.

Now our colours are repeating themselves by the fifth element!

Where would I use this?

Anywhere you have discrete values next to each other where you want each to be visually distinct to the elements either side. A good example might be in a pie chart:

Does it always have to start with red? 🔴

No, not at all! You can simply add a random offset to your start value, as such:

const hue = offset + ((i * 137) % 360);

where

const offset = Math.random() * 360;

Is this related to the Golden Ratio?

Yes, the Golden Angle is closely related to the Golden Ratio, which has a value of approximately 1.618.

goldenAngle = 137.508;
restOfCircle = 360 - goldenAngle;
ratio = restOfCircle / goldenAngle;

ratio === ~1.618;

You can try this out for yourself — the ratio between the larger angle of the circle and the angle covered by the golden angle, is actually the golden ratio. You can see this in the image labelled “The Golden Angle” above with the circle dissected into lengths a and b.

Sounds good in theory — but my users may well be colour blind! How does this help them?

The original example, run through an online deuteranopia simulator.

When run through various colour blind simulators, the generated colours hold up fairly well. This only holds if the goal is to have adjacent elements stand out, opposed to trying to have clearly unique identifying colours per element.

That being said, I am not an expert on colour-blindness. I wouldn’t recommend using colour as your only way of differentiating key elements of your web page. You should include clear, stand out titles and photos, or maybe numbering systems — colour should be a single part of your design.

Closing thoughts ☁️

This can be a simple way to add some colour to a design. If you’ve used this trick or a similar one to good effect anywhere, I’d love to hear about it :)