Why does HTML think “chucknorris” is a color?
某些随机字符串在HTML中作为背景色输入时如何产生颜色?例如:
1 | <body bgcolor="chucknorris"> test </body> |
…在所有浏览器和平台上生成具有红色背景的文档。
有趣的是,虽然
这是怎么回事?
这是网景时代的遗留物:
Missing digits are treated as 0[...]. An incorrect digit is simply interpreted as 0. For example the values #F0F0F0, F0F0F0, F0F0F, #FxFxFx and FxFxFx are all the same.
这是来自于博客文章对微软Internet Explorer的颜色分析的一点抱怨,它详细地介绍了它,包括不同长度的颜色值等。
如果我们从博客文章中依次应用这些规则,我们将得到以下信息:
用0替换所有无效的十六进制字符
1 | chucknorris becomes c00c0000000 |
填充到下一个可被3整除的字符总数(11->12)
1 | c00c 0000 0000 |
分成三个相等的组,每个组分代表一种RGB颜色的相应颜色组分:
1 | RGB (c00c, 0000, 0000) |
将每个参数从右向下截断为两个字符
结果如下:
1 | RGB (c0, 00, 00) = #C00000 or RGB(192, 0, 0) |
下面是一个示例,演示了
1 2 3 4 5 6 7 8 9 10 11 12 | <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> |
这也回答了问题的另一部分:为什么
1 | c00c00000 => c00 c00 000 => c0 c0 00 [RGB(192, 192, 0)] |
它是浅黄色的金黄色。当字符串以9个字符开始时,我们将保留第二个C,因此它将以最终的颜色值结束。
我最初遇到这种情况的时候,有人指出你可以做
不好意思,我不同意,但是根据@yuhong bao发布的分析传统颜色值的规则,
规则规定:
- 通过添加0s使字符串的长度为3的倍数:
chucknorris0 。 - 将字符串分成3个等长字符串:
chuc knor ris0 。 - 将每个字符串截断为2个字符:
ch kn ri 。 - 保留十六进制值,必要时加0:
C0 00 00 。
我能够使用这些规则正确地解释以下字符串:
LuckyCharms Luck LuckBeALady LuckBeALadyTonight GangnamStyle
最新消息:最初说颜色是
大多数浏览器只会忽略颜色字符串中的任何非十六进制值,将非十六进制数字替换为零。
注意,这不适用于遵循CSS标准的CSS颜色分析。
1 2 3 4 5 6 7 8 9 | <p> <font color='chucknorris'>Redish</font> </p> <p> <font color='#c00000'>Same as above</font> </p> <p> <span style="color: chucknorris">Black</span> </p> |
浏览器试图将
这似乎主要是Internet Explorer和Opera(12)的问题,因为Chrome(31)和Firefox(26)都忽略了这一点。
另外,括号中的数字是我测试过的浏览器版本。
.
轻一点的音符
Chuck Norris doesn't conform to web standards. Web standards conform
to him. #BADA55
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位,这就是忽略前导零的原因。
更新:此代码与规范中定义的代码不完全匹配,但唯一的区别是有几行代码。我认为是添加了这些行(在Netscape 4中):
1 2 3 4 | if (bytes_per_val > 4) { bytes_per_val = 4; } |
原因是浏览器无法理解它,并试图以某种方式将其转换为它可以理解的内容,在本例中转换为十六进制值!…
所以十六进制格式的
现在他们被
但是我们知道有效的十六进制对于rgb只有2个字符,意味着
所以真正的结果是:
1 | bgcolor="#c00000"; |
我还添加了图片中的步骤作为快速参考:
答:
- 浏览器将尝试将chucknorris转换为十六进制值。
- 由于
c 是chucknorris中唯一有效的十六进制字符,因此该值变为:c00c00000000 (0表示所有无效的值)。 - 然后,浏览器将结果分成3组:
Red = c00c 、Green = 0000 、Blue = 0000 。 - 由于HTML背景的有效十六进制值仅包含每种颜色类型(R、G、B)的2位数字,因此每个组中最后2位数字都会被截断,剩下的rgb值为
c00000 ,这是砖红色调的颜色。
chucknorris是用C来统计的,浏览器读取十六进制值。
because a,b,c,d,e,f are characters in hexadecimal
浏览器
然后,
c00c00000000 =>R:c00c,G:0000,B:0000
浏览器只需要2位数字来指示颜色。
R:c00c,G:0000,B:0000 =>R:c0,G:00,B:00 =>c00000
最后,在Web浏览器中显示
下面是一个例子
1 2 3 4 5 6 7 | <table> <tr> <td bgcolor="chucknorris" cellpadding="10" width="150" align="center">chucknorris</td> <td bgcolor="c00c00000000" cellpadding="10" width="150" align="center">c00c00000000</td> <td bgcolor="c00000" cellpadding="10" width="150" align="center">c00000</td> </tr> </table> |
分析遗留属性颜色的规则涉及到比现有答案中提到的步骤更多的步骤。截断组件到2位部分描述如下:
一些例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | oooFoooFoooF 000F 000F 000F <- replace, pad and chunk 0F 0F 0F <- leading zeros truncated 0F 0F 0F <- truncated to 2 characters from right oooFooFFoFFF 000F 00FF 0FFF <- replace, pad and chunk 00F 0FF FFF <- leading zeros truncated 00 0F FF <- truncated to 2 characters from right ABCooooooABCooooooABCoooooo ABC000000 ABC000000 ABC000000 <- replace, pad and chunk BC000000 BC000000 BC000000 <- truncated to 8 characters from left BC BC BC <- truncated to 2 characters from right AoCooooooAoCooooooAoCoooooo A0C000000 A0C000000 A0C000000 <- replace, pad and chunk 0C000000 0C000000 0C000000 <- truncated to 8 characters from left C000000 C000000 C000000 <- leading zeros truncated C0 C0 C0 <- truncated to 2 characters from right |
下面是算法的部分实现。它不处理用户输入有效颜色的错误或情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | function parseColor(input) { // todo: return error if input is"" input = input.trim(); // todo: return error if input is"transparent" // todo: return corresponding #rrggbb if input is a named color // todo: return #rrggbb if input matches #rgb // todo: replace unicode code points greater than U+FFFF with 00 if (input.length > 128) { input = input.slice(0, 128); } if (input.charAt(0) ==="#") { input = input.slice(1); } input = input.replace(/[^0-9A-Fa-f]/g,"0"); while (input.length === 0 || input.length % 3 > 0) { input +="0"; } var r = input.slice(0, input.length / 3); var g = input.slice(input.length / 3, input.length * 2 / 3); var b = input.slice(input.length * 2 / 3); if (r.length > 8) { r = r.slice(-8); g = g.slice(-8); b = b.slice(-8); } while (r.length > 2 && r.charAt(0) ==="0" && g.charAt(0) ==="0" && b.charAt(0) ==="0") { r = r.slice(1); g = g.slice(1); b = b.slice(1); } if (r.length > 2) { r = r.slice(0, 2); g = g.slice(0, 2); b = b.slice(0, 2); } return"#" + r.padStart(2,"0") + g.padStart(2,"0") + b.padStart(2,"0"); } $(function() { $("#input").on("change", function() { var input = $(this).val(); var color = parseColor(input); var $cells = $("#result tbody td"); $cells.eq(0).attr("bgcolor", input); $cells.eq(1).attr("bgcolor", color); var color1 = $cells.eq(0).css("background-color"); var color2 = $cells.eq(1).css("background-color"); $cells.eq(2).empty().append("bgcolor:" + input,"","getComputedStyle:" + color1); $cells.eq(3).empty().append("bgcolor:" + color,"","getComputedStyle:" + color2); }); }); |
1 2 3 | body { font: medium monospace; } input { width: 20em; } table { table-layout: fixed; width: 100%; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"> <p> <input id="input" placeholder="Enter color e.g. chucknorris"> </p> <table id="result"> <thead> <tr> <th>Left Color</th> <th>Right Color</th> </tr> </thead> <tbody> <tr> <td> </td> <td> </td> </tr> <tr> <td> </td> <td> </td> </tr> </tbody> </table> |