Occasionally when developing a proof of concept, we require a simple colour palate in order to make the work look a little more polished. A quick trick for doing this, presuming you have a base colour to start with, is to open something like Photoshop and create a palette by copying the colour a desired number of times, decreasing the opacity by 10% to give you a different tints of that colour.

When it occurred to me that this should be possible to do with client technologies, the challenge was accepted. While it's easy to render a series of colour boxes with the differing amounts of opacity using CSS, the trick is calculating what the exact resulting colour value will be. After sorting out some math, I came up with the following demo:

Enter a hex colour in the text box above and press enter.

How Does it Work?

In order to calculate the opacity of a given RGB colour, we need to first break it apart into it's separate decimal colour values. Once we have the different values of red, green and blue, we then can apply the following formula to each get the new corresponding colour values:

result = opacity x colour + (1 - opacity) x background

The important thing to note here is that this depends on the background colour one wishes to use - which in our case will be white (aka "#ffffff" in hexadecimal). So for example, given a pleasant orange colour of #ff6600, when we separate this into the corresponding values for red, green and blue, we end up with 255, 102 and 0. If we want to apply 90% opacity, we end up with equations like so:

Colour Equation Dec Value Hex Value
Red 0.90 x 255 + (1 - 0.90) x 255 255 FF
Green 0.10 x 102 + (1 - 0.90) x 255 117 75
Blue 0.10 x 0 + (1 - 0.10) x 255 25 19


...or for those of you who like code, this is the equation expressed in javascript:

var result = Math.round((opacity*colour)+((1-opacity)*255));


As you can see from this example, after applying an opacity of 90%, the resulting hexadecimal colour code will be #FF7519 (given a white background). Remember that the background colour is also separated into the corresponding RGB values, which for white is a decimal value of 255 for each.

Some of you may have also noticed the resulting values above have been rounded. In fact I played with the rounding quite a bit only to find that in the end it made no visual difference (on my monitor anyway). Using a a cool screen colour sampling app, I checked my results against what it was sampling and noticed that occasionally the code would be off by 1 compared to the sampler. Deciding to see the difference for myself, I rendered the calculated colour below the the original colour with opacity applied and could see no difference. Can you? In any event, this works great for a quick colour palette.