Since you are "interested in seeing the science behind why it occurs, if there is an explanation for it"...
TLDR:
'Color-values' are not 'universal'.
The abbreviated/shorthand three-digit hexadecimal #RGB
form is described in the CSS specification, not in HTML.
As a result, the three-digit form in an attribute other than "style" or inside a <style>
tag is not interpreted as a valid color in some browsers.
https://en.wikipedia.org/wiki/Web_colors
In depth:
I'm starting with the CSS 1 spec, Color units (6.3) (as it introduces some terms/concepts I then don't have to repeat), which specifies:
A color is a either a keyword or a numerical RGB specification.
The suggested list of keyword color names is: aqua, black, blue,
fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver,
teal, white, and yellow. These 16 colors are taken from the Windows
VGA palette, and their RGB values are not defined in this
specification.
BODY {color: black; background: white }
H1 { color: maroon }
H2 { color: olive }
The RGB color model is being used in numerical color specifications.
These examples all specify the same color:
EM { color: #f00 } /* #rgb */
EM { color: #ff0000 } /* #rrggbb */
EM { color: rgb(255,0,0) } /* integer range 0 - 255 */
EM { color: rgb(100%, 0%, 0%) } /* float range 0.0% - 100.0% */
The format of an RGB value in hexadecimal notation is a '#
'
immediately followed by either three or six hexadecimal characters.
The three-digit RGB notation (#rgb
) is converted into six-digit form
(#rrggbb
) by replicating digits, not by adding zeros. For example,
#fb0
expands to #ffbb00
. This makes sure that white (#ffffff
) can be
specified with the short notation (#fff
) and removes any dependencies
on the color depth of the display.
The format of an RGB value in the functional notation is 'rgb(
'
followed by a comma-separated list of three numerical values (either
three integer values in the range of 0-255, or three percentage values
in the range of 0.0% to 100.0%) followed by ')
'. Whitespace characters
are allowed around the numerical values.
Values outside the numerical ranges should be clipped. The three rules
below are therefore equivalent:
EM { color: rgb(255,0,0) } /* integer range 0 - 255 */
EM { color: rgb(300,0,0) } /* clipped to 255 */
EM { color: rgb(110%, 0%, 0%) } /* clipped to 100% */
RGB colors are specified in the sRGB color space. UAs may vary in the
fidelity with which they represent these colors, but use of sRGB
provides an unambiguous and objectively measurable definition of what
the color should be, which can be related to international standards.
In the context of CSS, with regard to browser-support, the only 2 'interesting' things I could find were:
- All browsers that support style sheets (version 3 and above, except IE3 Mac) support this three-character shorthand form of hexadecimal colors (Sources: 1, 2, "Optimize CSS Colors" by King A.B.)
Note the historical timeframe of that text.. IE3... on Mac... Browsers like FireFox 1 or Chrome weren't even around back then..
- The two
rgb()
methods suffer from Internet Explorer 3's non-support for them
Source: 1 (very good read)
According to the HTML4 spec, the attribute bgcolor
was only for <body>
, <table>
, <tr>
, <th>
and <td>
. (So as far as the legacy spec is concerned, one can not use it on a <div>
for example.)
All of them are of the CDATA
-type: %Color;
which was defined as:
<!ENTITY % Color "CDATA" -- a color using sRGB: #RRGGBB as Hex values -->
<!-- There are also 16 widely known color names with their sRGB values:
Black = #000000 Green = #008000
Silver = #C0C0C0 Lime = #00FF00
Gray = #808080 Olive = #808000
White = #FFFFFF Yellow = #FFFF00
Maroon = #800000 Navy = #000080
Red = #FF0000 Blue = #0000FF
Purple = #800080 Teal = #008080
Fuchsia= #FF00FF Aqua = #00FFFF
-->
The magic phrase here is: "a color using sRGB: #RRGGBB as Hex values".
If I read this wearing a specification-implementor's hat, I must agree that I don't see short-hand 3-digit #RGB
notation specified and I would not have implemented it (neither would I have implemented RGB(DDD,DDD,DDD)
).
As for HTML5, the bgcolor
attribute is obsoleted for all previous (HTML4) specified elements (see above).
That means that, in regard to specification, the format of valid 'color-codes' is not going to change any time soon..
Conclusion:
Accepting only a named color (from a specified/supported list) or a 'hex triplet' (format #RRGGBB
) sRGB color-value on the HTML attribute bgcolor
is not a bug; it is per spec!
Cross-Browser solution: .. see spec ?
If one mistakingly specifies a short-hand color-value for bgcolor
on a parsing/rendering engine that doesn't support that, then either nothing happens or a unintended color might show; effectively you have entered 'Chuck Norris'-land..
Most notably for MS IE and MS Outlook, the colors will seem almost black. For example: #ff0
(shorthand) will become #0f0f00
(instead of #ffff00
). Another example: #07c
will become #00070c
, etc.
However some other implementations turn #ff0
into #000ff0
and #07c
into #00007c
!!
If one mistakingly specifies an RGB(RRR,GGG,BBB)
value for bgcolor
, all kinds of colors can appear, for example RGB(255,255,255)
can become a very dark shade of green source, etc.
So here we have a fun example where Microsoft's Internet Explorer (all known versions, including IE11) did follow the spec and a lot of people still complain..
I found countless bug-rapports regarding "the 3-digit color-value shorthand 'bug' for the bgcolor
-attribute" (spanning over 15 years) addressed at for example MS IE, alternative browsers using MS IE HTML parse/rendering engine and the majority of local-app/webbased Email-clients like Gmail, (all versions of) Outlook(-Express), Lotus Notes, Android, etc. etc. etc. (for example 1, 2, 3, 4, 5, etc.)
Why the complaints/bug-rapports?
Because some other browsers (like FireFox, Chrome) did/do support color-values in other formats then #RRGGBB
on HTML's attribute bgcolor
.
Why do others support it?
I have just 2 guesses: (a) It's a leftover from "BrowserWar 1" where one of the battles was around "My browser can make 'sense' of bigger cr@p-code then the competitor's", but somewhat more likely would be (b) reusing the code from the CSS color-value parser... eventually I would have done that as well
Extra:
Why would anyone anno 2015 still care about bgcolor
?
Why does that still generate such an amount of bug-rapports and questions?
The answer is HTML Email...
In theory (to the unsuspecting web-developer) it's 'just HTML and CSS'..
In practice it's amazingly hard (1) to get right. Think: all cross-browser issues that ever existed to the power of 3 !
It has to work on far more E-mail clients on numerous platforms (loads of 'legacy' applications that are actually still in use), it must also work in web-based clients like Gmail, AOL, Yahoo, Hotmail, etc. etc.
Not only must they code for the lowest common denominator imaginable (much techniques were already considered ancient a fat decade ago), they must even try to 'fit in' with the layout/style of some of the web-based clients.
Their typical structure is one big background table, then one div, then one main table, and nested tables if needed...
To put things into further perspective, according to litmus (anno 2014):
"It turns out that the most reliable way of coding background colors is to use the HTML bgcolor
attribute with a 6-digit hex code on the table and td level"
Clearly this 'mess' is not going to dis-appear soon and a common thing for a web-developer is to code/design HTML e-mail... Therefore I think that a good complete understanding (and answer to this matter) is still very relevant anno 2015 and the near future.
Hope this helps!
PS: MS IE's filter: progid:DXImageTransform.Microsoft.gradient
also doesn't accept 3-digit hex shorthand color values, but now that one is reminded of the notion that 'Color-Values are not Universal', this is less of a surprise (and not a bug unless it was specified that it would accept such values).