为什么某些随机字符串在HTML中作为背景颜色输入时能产生颜色?比如说。
<body bgcolor="chucknorris"> test </body>
...在所有的浏览器和平台上产生一个具有**红色背景的文档。
有趣的是,虽然chucknorri
也产生红色背景,但chucknorr
产生黄色背景。
这到底是怎么回事?
这是从网景时代留下来的。
缺少的数字被视为0[...]。例如,#F0F0F0、F0F0F、F0F0F、#FxFxFx和FxFxFx的值都是一样的。
这是来自博文A little rant about Microsoft Internet Explorer''s color parsing中的内容,其中包括颜色值的不同长度等,非常详细。
如果我们依次应用博文中的规则,我们会得到以下结果。
1.用0's替换所有非有效的十六进制字符
chucknorris变成c00c0000000
2.填充到可被3除以的下一个字符总数(11 -> 12)。
c00c 0000 0000
3.分成三个相等的组,每个分量代表一个RGB颜色的相应颜色分量。
RGB (c00c, 0000, 0000)
4.将每个参数从右边截断为两个字符
从而得到以下结果。
RGB (c0, 00, 00) = #C00000 or RGB(192, 0, 0)
下面是一个例子,展示了bgcolor
属性的作用,产生了这个"惊人"的颜色图谱。
<table>
<tr>
<td bgcolor="chucknorris" cellpadding="8" width="100" align="center">chuck norris</td>
<td bgcolor="mrt" cellpadding="8" width="100" align="center" style="color:#ffffff">Mr T</td>
<td bgcolor="ninjaturtle" cellpadding="8" width="100" align="center" style="color:#ffffff">ninjaturtle</td>
</tr>
<tr>
<td bgcolor="sick" cellpadding="8" width="100" align="center">sick</td>
<td bgcolor="crap" cellpadding="8" width="100" align="center">crap</td>
<td bgcolor="grass" cellpadding="8" width="100" align="center">grass</td>
</tr>
</table>
这也回答了问题的另一部分;为什么bgcolor="chucknorr"
会产生一个黄色的颜色?好吧,如果我们运用规则,这个字符串是。
c00c00000 => c00 c00 000 => c0 c0 00 [RGB(192, 192, 0)]
这就产生了一个浅黄色的金色。由于该字符串一开始是9个字符,我们这次保留了第二个C,因此它最终出现在最终的颜色值中。
我最初遇到这个问题时,有人指出你可以做color="crap"
,而且,结果是棕色。
大多数浏览器会简单地忽略颜色字符串中的任何NON-hex值,用零代替非hex数字。
ChuCknorris
翻译成c00c0000000
。 在这一点上,浏览器将把字符串分成三个相等的部分,表示红、绿和蓝值。c00c 0000 0000
。 每个部分的额外位将被忽略,这使得最后的结果是#c00000
,这是一个红色的颜色。
注意,这并不*适用于CSS颜色解析,它遵循CSS标准。
<p><font color='chucknorris'>Redish</font></p>
<p><font color='#c00000'>Same as above</font></p>
<p><span style="color: chucknorris">Black</span></p>
WHATWG HTML规范中有解析传统颜色值的确切算法。 https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value
Netscape Classic用于解析颜色字符串的代码是开源的。 https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155
例如,注意到每个字符都被解析为一个十六进制数字,然后被移到一个32位的整数中,**不检查溢出情况。只有8个十六进制数字适合32位整数,这就是为什么只考虑最后8个字符。在将十六进制数字解析为32位整数后,再将其截断为8位整数,即用16除以8位,直到适合8位为止,这就是前导零被忽略的原因。
更新:这段代码与规范中的定义不完全一致,但其中唯一的区别是几行代码。我认为就是这几行被添加了(在Netscape 4中)。
if (bytes_per_val > 4)
{
bytes_per_val = 4;
}