Why you can display all words as colors in a webbrowser

Why you can display all words as colors in a webbrowser

Have you ever tried to set something weird as a background color like bgcolor="foo bar baz"? Chances are you haven’t, because you’re smart, aware of hex / rgb rules and you know that some attributes are deprecated in html5 anyway. But the fact remains that you can display literally anything as a color in all modern browsers.

Let’s have a look at the following examples:
foo bar baz, I'm the president, 1r2a3n4d5o6m7w8o9r0d and James Star. Here are the results:

input:foo bar bazI'm the president1r2a3n4d5o6m7w8o9r0dJames Star
expected:rgb(240, 186, 186)rgb(0, 224, 13)rgb(16, 213, 128)rgb(10, 0, 160)

So the question is, how does a webbrowser interpret invalid strings and converts them to a valid color?

Short answer

All major webbrowsers use an algorithm for this. The most important points are:

  • Strip whitespaces from string.
  • Check if string is multiple of three. If not, add 0‘s to the string until it is.
  • Change each non-hexadecimal value (0-9,a-f) to 0.
  • Divide string into three equal length substrings.
  • Truncate each resulting substring to two characters.
  • Display resulting color (with RGB values).


  1. Strip whitespaces: I'm the president becomes I'mthepresident.
  2. Multiple of three? Yes, I'mthepresident = 15 characters.
  3. Change non-hex to 0: I'mthepresident becomes 00000e00e00de00.
  4. Three equal length parts: 00000e00e00de00 becomes 00000 e00e0 0de00.
  5. Truncate each string to two characters: 00000 e00e0 0de00 becomes 00 e0 0d.
  6. Display as RGB: 00 => 0*16+0=0, e0 => 14*16+0=224, 0d => 0*16+13=13. Result: (0,224,13).

Try it yourself!

Some suggestions you might want to try:

  • Your name
  • Your favorite meal
  • Name of your boss
  • Your favorite website
  • Names of celebrities
  • This website

How to convert Hex to RGB

Before we get to the more special stuff, lets be sure that you know how to convert Hex to RGB properly. It’s really simple. While the hexadecimal values 0-9 means just that, a-f calculates as 10-15. You normally have six values total, led by a # like #123456. Just pair them to groups: 12 34 56. To convert to RGB, the first number of each group gets multiplied by 16. The second number just gets added to the result of the first number. It acts as an “offset” which means it has not such a big impact on the final result as the first number. Here is an example: #123456 => 12 34 56 => convert to RGB: 1*16+2 3*16+4 5*16+6 => rgb(18,52,86)

Digging deeper

Now we can look at some special cases where the results differ from what is expected. The short answer at the beginning works for almost anything. However, there are some exceptions.

  • Hardcoded words: 140 colornames like blue, yellow, green, white etc are hardcoded and will just return the associated color. Additionally, the word transparent (or no input at all) will not generate a color value.
  • Long inputs: Your string may not be longer than 128 characters. This is the limit. Additional characters get truncated.
    • If the resulting three substrings are longer than eight characters, the leading characters are removed until there are only eight left. So 1234567890 1234567890 1234567890 becomes 34567890 34567890 34567890 which in turn becomes 343434 or rgb(52,52,52).
    • Also, if all your substrings start with one or more leading 0‘s, they will get removed. While 10023456 10023456 10023456 becomes 101010 or rgb(16,16,16), 10xy23456 10xy23456 10xy23456 becomes 0xy23456 0xy23456 0xy23456 (reduced to eight characters) and in the next step becomes 23456 23456 23456 (because all substrings had technically three leading 0‘s). The final result would be 232323 or rgb(35,35,35).
  • Short inputs (no leading #):
    • One character: One hex value (0-9,a-f) results in rgb(0-15,0,0), not rgb(0-240,0,0) (note: This only applies for one, two and three character inputs), everything else is set to 0.
    • Two characters: The second value determines the green portion of RGB (not the offset red portion). The input a2 becomes rgb(10,2,0) not (162,0,0) or (12,0,0).
    • Three characters: The third value determines the blue portion of RGB (not the first green portion). The input a2b becomes rgb(10,2,11).
    • Four characters: The first two values determine the red portion of RGB (note: From now on the values range from 0-240+offset, not 0-15+offset). The last two values determine the green portion of RGB. The input a2b3 becomes rgb(162,179,0).
    • Five characters: The fifth value determines the main blue portion of RGB. So xyz12 becomes rgb(0,1,32).
  • Short inputs (with leading #):
    • One character: Same as without leading #. #5 becomes rgb(5,0,0).
    • Two characters: Same as without leading #. #5a becomes rgb(5,10,0).
    • Three characters: Major changes. The algorithm duplicates each value after the leading #. So #5a1 is treated as #55aa11 and becomes rgb(85,170,17).
    • Four characters: Same as without leading #.
    • Five characters: Same as without leading #.
  • If there are more than six characters and a leading #, then simply remove the leading #.

Can’t remember all this, too much geek info!

No problem. Here is the ultra short “works almost always and makes me happy” version:
“Count string. Divide by 3. Truncate each substring to two characters. Convert to RGB.”
This works 95% of the time for most commonly used invalid “colors”. If something unexpected happens, check for removable leading zeros. Then you’ll cover 99%. If result is still weird, check the length of substrings or just come back here and read about the other special cases.

Tried it, can’t get it to work!

It’s true that bgcolor is deprecated and discontinued in html5, but it’s also still supported for a long time to come by all major browsers for compatibility reasons. Then “what am I doing wrong?” Well, invalid “colors” like these do not work via CSS. You’ll likely run into an “invalid property” warning. Since there is no css-property or css-attribute for bgcolor, it appears you can only apply these kinds of “colors” with bgcolor directly to the appropriate elements. These are table, tr, td, th and body. If you applied it to let’s say a div– or a p-tag, you are right, it won’t work.

Hope you found this post useful and that it cleared up a few things for you. So, have a nice day!


Leave a Reply

Your email address will not be published. Required fields are marked *