Recently, Shazam introduced a brand new, visually more appealing way to accommodate ads in the app. This new ad format overtakes the whole screen with a smooth animation. The experience not only looks better, but also feels less interruptive and way more engaging.
Designers tend to think of advertising as a necessary evil. Ads are external content that need real estate on our pixel-perfect, unique design. The UI has colours, the ads have colours. It’s not easy to apply a dozen of them to our interfaces and make them work together. It takes a process of studying colour theory and playing around with rules to have confidence and control over what looks and functions well on the screen.
In this case, the ads need to stand out without interrupting the core experience. What we want to achieve here is a tool for third party clients that excludes certain colours from the acceptable mix. A tool that works with a single HEX code as input and tells if a particular colour matches our defined criteria. We would like to filter out too light colours that damage usability and washed-out colours that make the experience less desirable. In order to do this, we will need to squeeze out these values from a single HEX code.
Colours are the way our brain, through our eyes, interprets electromagnetic radiation of a wavelength within the visible spectrum. Yum. Visible light lies between 400 and 700 nanometers. Radiation with a wavelength of over 750 nm is called infra-red and radiation under 350 nm is ultra-violet.
A colour wheel is really just the spectrum twisted around so that the violet and red ends are joined. This wheel is particularly useful for showing how the colours relate to each other and how you can create new colours by mixing two or more colours.
RGB refers to a system for representing the colours to be used on a computer display. RGB is a combination of Red, Green and Blue. These colours can be combined in various proportions to obtain any colour in the visible spectrum.
Each level is measured by the range of decimal numbers from 0 to 255 (256 levels for each colour). For example, if a colour has zero Blue, it will be a mixture of Red and Green. This means we can generate 256 x 256 x 256 = 16.777.216 different colours with this model.
It is important to note that different devices detect or reproduce a given RGB value differently. An RGB colour format is represented by its Red, Green and Blue values, no surprises here:
RGB = (54, 155, 229) | Note: 54 = Red, 155 = Green and 229 = Blue
HEX is a widely known and used format for defining colours on the web. The name comes from the phrase hexadecimal, which is used by humans to shorten binary to a more easily understandable form. Each of the HEX numbers use numbers and letters to represent values between 0–16. Numbers are used for the range 0–9 and letters A, B, C, D, E, F for the range 10–16.
The code itself is a HEX triplet, which represents 3 separate values that specify the levels of the component colours. These 3 values are called bytes and make up a six-digit hexadecimal number used in HTML, CSS, SVG and other computing applications.
The first value pair refers to Red, the second to Green and the third to Blue. One byte represents a number in the range 0 to 255 in decimal notation. In hexadecimal notation, the scale goes from the lowest (00) to the highest (FF) intensity of each colour. HEX codes start with a hashtag sign and are followed by the mentioned format:
HEX = #A3D645 | Note: A3 = Red, D6 = Green and 45 = Blue
Conversion between RGB & HEX
We will transform an RGB code into a HEX code. What this truly means is that we need to convert decimal numbers from given RGB values to hexadecimals. In order to do this, we will divide our values by 16.
R / 16 = X1 + Y1G / 16 = X2 + Y2B / 16 = X3 + Y3
In the above mentioned formula, X is called the quotient and Y is the remainder. These two numbers are used to represent the HEX value pair for each particular colour, Red, Green and Blue. A HEX code can be calculated from these values as #X1Y1X2Y2X3Y3 where X1Y1 are the values for Red, X2Y2 for Green and X3Y3 for Blue. Let’s have a look at this with the following RGB values: (54, 155, 229)
R = 54 / 16 = 3 + 6G = 155 / 16 = 9 + 11 | Note: 11 = B in hexadecimalB = 229 / 16 = 14 + 5 | Note: 14 = E in hexadecimal
Voila, our code (54, 155, 229) in RGB becomes #369BE5 in HEX
We can also make the conversion work in reverse. In case we would like to transform HEX codes into RGB codes, all we have to do is to multiply the quotients by 16 and add the remainders.
R = X1 x 16 + Y1G = X2 x 16 + Y2B = X3 x 16 + Y3
We already know the quotients (X1, X2, X3) and remainders (Y1, Y2, Y3). A HEX code consists of these values as #X1Y1X2Y2X3Y3. Let’s try converting back our HEX code: #369BE5
R = 3 x 16 + 6 = 54G = 9 x 16 + 11 = 155 | Note: 11 = B in hexadecimalB = 14 x 16 + 5 = 229 | Note: 14 = E in hexadecimal
There we go, our code #369BE5 in HEX becomes (54, 155, 229) in RGB
What do you call friends who like maths?
Keep smiling. We’re off to continue our journey to the world of HSL.
HSL is a common cylindrical coordinate representation of points in an RGB colour model. HSL stands for Hue, Saturation and Luminosity. Hue refers to the colour family of the specific colour we’re looking at. It indicates the actual dominant colour on the RGB colour wheel. Luminosity refers to how much white or black is mixed in the colour. Saturation indicates the amount of grey in the same colour.
Conversion between RGB & HSL
Luminosity (also called brightness, lightness or luminance) stands for the intensity of the energy output of a visible light source. It basically tells how light a colour is and is measured on the following scale: L = [0, 1]
It’s time to introduce the maximum and minimum values among our RGB numbers. Max(RGB) stands for the highest and Min(RGB) for the lowest value across Red, Green and Blue. In order to make our further calculations work, we need to convert the RGB values to the range 0–1. This can be done by dividing them by 255. Let’s take our existing RGB values for example: (54, 155, 229)
R = 54 / 255 = 0,212G = 155 / 255 = 0,608B = 229 / 255 = 0,898
The Luminosity of the RGB colour (54, 155, 229) can be calculated from the Max(RGB) and Min(RGB) values as follows:
L = (1 / 2) x (Max(RGB) + Min(RGB))
From our R, G and B numbers, R seems to be the smallest and B the largest. We now know the Max(RGB) = B = 0,898 and Min(RGB) = R = 0,212 values.
L = (1 / 2) x (0,898 + 0,212) = 0,555 ~ 56%
Most sources of visible light contain energy over a band of wavelengths. Hue is the wavelength within the visible light spectrum at which the energy output from a source is greatest. It is indicated by its position (in degrees) on the RGB colour wheel: H= [0°, 360°]
The formula for Hue depends on how RGB values relate to each other. In other words, it depends on which one represents the Max(RGB) and Min(RGB) values.
(A) If R ≥ G ≥ B | H = 60° x [(G-B)/(R-B)](B) If G > R ≥ B | H = 60° x [2 - (R-B)/(G-B)](C) If G ≥ B > R | H = 60° x [2 + (B-R)/(G-R)](D) If B > G > R | H = 60° x [4 - (G-R)/(B-R)](E) If B > R ≥ G | H = 60° x [4 + (R-G)/(B-G)](F) If R ≥ B > G | H = 60° x [6 - (B-G)/(R-G)]
The Hue of the RGB colour (54, 155, 229) can be calculated using the right formula from the pool above. Don’t forget to divide by 255 before going any further.
R = 54 / 255 = 0,212G = 155 / 255 = 0,608B = 229 / 255 = 0,898
B > G > R seems to stand true, our match is (D).
H = 60° x [4 - (0,608-0,212)/(0,898-0,212)] = 205,4°
Saturation is an expression for the relative bandwidth of the visible output from a light source. As saturation increases, colours appear more pure. As saturation decreases, colours appear more washed-out. It is measured on the following scale: S = [0, 1]
The formula for Saturation uses the Min(RGB), Max(RGB) values and Luminosity.
(A) If L < 1 | S = (Max(RGB) — Min(RGB)) / (1 — |2L - 1|)(B) If L = 1 | S = 0
We have calculated the Luminosity before, L = 0,555. Our formula will be (A) as L = 0,555 < 1. We also know Max(RGB) = 0,898 and Min(RGB) = 0,212. We finally have everything we needed for Saturation. Good stuff.
S = (0,898 — 0,212) / (1 — |2 x 0,555 - 1|) = 0,770 ~ 77%
We have successfully calculated Luminosity, Hue and Saturation from a single HEX code
Now we can define our own rules for accepting colours solely relying on a HEX code. For example, we can set a desired range for the Luminosity or exclude certain colours from the colour wheel with Hue. With Saturation we can also influence how washed-out or colourful our screens look.
L = 56%H = 205,4°S = 77%
At Shazam we have decided to only accept colours with a Luminosity value smaller than a certain level (excluding too light colours) and changed this rule for a specific spectrum on the colour wheel. This way we could get rid of some bright yellows and greens. By using the conversion formulas in a script, we can also build a simple tool that helps with this process.
You can download a sample Colour Picker using these formulas.
Thanks (and claps) to Nikita Kardakov for helping with the code.