Thursday 18 January 2007 — This is almost 18 years old. Be careful.
I was experimenting with HTML color names the other day. This HTML snippet:
<p><font color='red'>█ RED</font></p>
got me some red text:
█ RED
(I’m using the Unicode FULL BLOCK 2588 character to get a solid swatch without having to worry about antialiasing effects). Adding a less well-known name got me another color:
<p><font color='red'>█ RED</font></p>
<p><font color='seagreen'>█ SEAGREEN</font></p>
█ RED
█ SEAGREEN
What if the name had a space in it?
<p><font color='red'>█ RED</font></p>
<p><font color='seagreen'>█ SEAGREEN</font></p>
<p><font color='sea green'>█ SEA GREEN</font></p>
To my surprise, the “sea green” line was blue! It seems the color name parser in your typical HTML browser is very forgiving, just like the rest of HTML interpretation. Given a nonsense string like “sxbxxsree”, it will decide that some subset of the characters indicate a color, and it will use them.
I played around with more randomized color names, and ended up with a brainteaser on my hands: how exactly does the browser interpret these bogus color names? Note that IE and Firefox don’t agree, though they are close.
I can’t show the effect inline here, because the bogus colors have no effect if the page has real color specifications someplace else, so have a look at the results in a separate page.
Here’s what different browsers show:
Color | Firefox | IE7 | Opera |
---|---|---|---|
red | █ #ff0000 | █ #ff0000 | █ #ff0000 |
seagreen | █ #2e8b57 | █ #2e8b57 | █ #2e8b57 |
sea green | █ #0e00ee | █ #0e00ee | █ #0ea00e |
sxbxxsreen | █ #0000e0 | █ #0000e0 | █ #00b000 |
sxbxxsree | █ #00000e | █ #0b00ee | █ #00b000 |
sxbxxsrn | █ #000000 | █ #0b0000 | █ #00b000 |
sxbxeen | █ #000e00 | █ #0bee00 | █ #00b0ee |
sreen | █ #00ee00 | █ #00ee00 | █ #00ee00 |
ffff00 | █ #ffff00 | █ #ffff00 | █ #ffff00 |
xf8000 | █ #0f8000 | █ #0f8000 | █ #0f8000 |
At least in the case of Firefox, I could go digging into the source to try to find what it is actually doing, but it is a head-scratcher. Clearly, it is interpreting the accidental hex characters, but how does it decide which ones to use where?
This is one of those fascinating cases where a black box reveals something of its insides through how it behaves when broken. Neurologists study people with head injuries for similar reasons!
Comments
red: #ff0000
seagreen: #2e8b57
sea green: #0ea00e
sxbxxsreen: #00b000
sxbxxsree: #00b000
sxbxxsrn: #00b000
sxbxeen: #00b0ee
sreen: #00ee00
ffff00: #ffff00
xf8000: #0f8000
For those who can't mentally translate hexcodes into colours, asidefrom the red and yellow there are various pleasant shades of green, except for sxbxeen which is close to cyan.
Opera and FF seem to agree that "Ned" is black and "Ned Batchelder" is green (though aqua-green and grass-green respectively).
Cathy: thanks. I've updated the table above to include the Opera colors.
Looking at "sea green", you can get "0e00ee" from reading a pair of hex digits, treating non-hex as '0', and then skipping a character before reading the next pair. So you'd get "0e" for "se", skip 'a', "00" for " g", skip 'r', and "ee" for "ee".
Looking at "sxbxxsree", you can get "00000e" from the same rule: "00" for "sx", skip 'b', "00" for "xx", skip 's', "0e" for "re".
Looking at "sxbxxsreen", you can get "0000e0" from almost the same rule, except you now skip two characters between pairs. So you'd get "00" for "sx", skip "bx", "00" for "xs", skip "re", and "e0" for "en".
Thus, the length of the string determines how many characters to skip. So the algorithm appears to basically be: split the whole string into three equal parts for the red, green, and blue components; and use the first two characters of each of these parts as the hex digits for the component (treating non-hex digits as '0'). The only modification necessary is to right-pad with '0' when the string cannot be evenly divided. So "sxbxxsreen" has length 10, which is not divisible by 3, but if we treat it as "sxbxxsreen00" we have the parts "sxbx", "xsre", and "en00", and then we consider "sx" as red, "xs" as green, and "en" as blue.
Can anyone find any exceptions? I haven't thought about IE, yet.
If that's it, then "#see" should be equivalent to "#00eeee" or "#00e0e0".
My guess as to why this happens is that it allows the browsers to interpret colors where you've delimited/grouped the components: "aa bb cc"; "aa,bb,cc"; and "aa, bb, cc" would all be #aabbcc. IE7 would even accept "(aa)(bb)(cc)".
One Sam Schinke looked into it a few years ago.
- IE doesn't handle the 'greys', except lightgrey as noted above by masukomi
- The CSS inherit keyword doesn't always work as expected in IE.
Add a comment: