Tiffany B. Brown

02 August 2017

Meet the #RRGGBBAA CSS color syntax

CSS color is about to get interesting. CSS Color Module Level 4 introduces new color spaces such as hwb() and lab(), and a color-mod() function that will let us change how we blend colors for the web.

But it also introduces some syntax changes to the mix, such as hexadecimal #rrggbbaa/#rgba notation. Since this change has shipped in some browsers, it's a good time to take a look.

RGB colors and hex values

But first, a quick refresher on RGB color. RGB — also abbreviated sRGB — is an additive color model. Red, green, and blue function as primary colors or channels that are mixed to form other colors. Mixing red and green for example, produces yellow, a secondary color.

Red + blue makes magenta. Red + green makes yellow. Green plus blue makes cyan

Each color channel in an RGB color is typically expressed as an integer between 0 and 255 — that's 00 through ff using a hexadecimal (base 16) system. The relative proportions of red, blue, and green determine what color our eyes perceive. Yellow, expressed using hexadecimal notation, is #ffff00. Both its red and green channels have the same maximum value (255 /ff).

#RRGGBBAA notation

#rrggbbaa notation works much the same way as #rrggbb notation, but with the addition of an alpha channel. Here too, accepted values range from 00ff. But rather than channel intensity, this value indicates transparency: 00 is fully transparent; ff is fully opaque.

Red, Green, and Blue at full opacity and about 50% opacity using RRGGBBAA notation

A fully opaque red, expressed using #rrggbbaa notation, is simply #ff0000ff. But let's say we wanted to use a red that was about 50% transparent. We could eyeball it, or use some math and JavaScript to calculate the hexadecimal value.

Converting from decimal to hex and back

As I mentioned earlier, color channel values range from 0 through 255, using a decimal system. We can convert any decimal number to a hexadecimal one using Number.prototype.toString().

Number.prototype.toString() accepts an optional radix or base argument between 2 (binary) and 32. To convert from decimal to hexadecimal, use 16.

console.log((16).toString(16)); // prints "10"

console.log((255).toString(16)); // prints "ff"

To find our 50% point, we need to multiply our maximum value of 255 by 0.5, and convert the result.

console.log((255 * 0.5).toString(16)); // prints "7f.8"

The value returned is 7f.8, which isn't valid for CSS. But dropping the .8 gets us pretty close. A 50% transparent red is roughly equivalent to #ff00ff7f.

Keep in mind that decimal numbers between 1 and 15 return a single character string. Left pad the value with a 0 before using it in CSS (e.g. 15 needs to be 0f instead of just f).

If you want to check your math, you can reverse the conversion — that is go from a hexadecimal to a decimal number — using parseInt. Using parseInt('7f', 16) returns 127. That's slightly less than 50% of 255.

Shortened #rgba syntax

The additional alpha channel value also applies to the shortened hexadecimal form. Just as we can use #f00 instead of #ff0000, we can use #f00f instead of #ff0000ff. All compute to opaque red (rgb(255, 0, 0)).

Browser support

To date, Firefox (49+) and Safari (10+) are the only browsers that support #rgba and #rrggbbaa notation out of the box. Support exists in Chrome, but Experimental Web Platform features must be enabled (see: chrome://flags) first.

It's safe to use this feature with a fallback, or stick to using the rgba() function.

Get CSS Master

Did you learn something from this blog post? You might like my book, CSS Master. It contains several nuggets of CSS joy like this one.

Buy now from SitePoint