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.
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 00
–ff
. But rather than channel intensity, this value indicates transparency: 00
is fully transparent; ff
is fully opaque.
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.