逐个丢弃前导零 as long as all components have a leading zero
丢弃除前2个以外的所有字符
一些例子:
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
以下是该算法的部分实现 . 它不处理用户输入有效颜色的错误或情况 .
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, "<br>", "getComputedStyle: " + color1);
$cells.eq(3).empty().append("bgcolor: " + color, "<br>", "getComputedStyle: " + color2);
});
});
body { font: medium monospace; }
input { width: 20em; }
table { table-layout: fixed; width: 100%; }
例如,请注意每个字符都被解析为一个十六进制数字然后被转换为32位整数 without checking for overflow . 只有八个十六进制数字适合32位整数,这就是为什么只考虑最后8个字符的原因 . 在将十六进制数字解析为32位整数之后,然后将它们除以16,将它们截断为8位整数,直到它们适合8位,这就是忽略前导零的原因 .
9 回答
浏览器正在尝试将
chucknorris
转换为十六进制颜色代码,因为它不是有效值 .在
chucknorris
中,除 c 之外的所有内容都不是有效的十六进制值 .因此它被转换为 c00c00000000 .
哪个成为 #c00000 ,一片红色 .
这似乎主要是 Internet Explorer 和 Opera (12)的问题,因为Chrome(31)和Firefox(26)都忽略了这一点 .
附:括号中的数字是我测试的浏览器版本 .
.
更轻松的说明
rules for parsing colors on legacy attributes涉及的步骤不同于现有答案中提到的步骤 . 截断组件为2位数部分描述为:
丢弃除最后8个之外的所有字符
逐个丢弃前导零 as long as all components have a leading zero
丢弃除前2个以外的所有字符
一些例子:
以下是该算法的部分实现 . 它不处理用户输入有效颜色的错误或情况 .
我很抱歉不同意,但根据解析@Yuhong Bao发布的遗留颜色值的规则,
chucknorris
不等于#CC0000
,而是等于#C00000
,一种非常相似但略有不同的红色色调 . 我使用Firefox ColorZilla add-on来验证这一点 .规则规定:
通过添加0使字符串的长度为3的倍数:
chucknorris0
将字符串分成3个相等长度的字符串:
chuc knor ris0
将每个字符串截断为2个字符:
ch kn ri
保留十六进制值,并在必要时添加0:
C0 00 00
我能够使用这些规则来正确解释以下字符串:
LuckyCharms
Luck
LuckBeALady
LuckBeALadyTonight
GangnamStyle
更新:原来的回答说,颜色是
#CC0000
已经编辑了他们的答案,包括更正 .Answer:
浏览器将尝试将 chucknorris 转换为十六进制值 .
由于
c
是 chucknorris 中唯一有效的十六进制字符,因此该值将变为:c00c00000000
( 0 for all values that were invalid ) .浏览器然后将结果分为3个分组:
Red = c00c
,Green = 0000
,Blue = 0000
.由于html背景的有效十六进制值仅包含每种颜色类型( r , g , b )的2位数字,因此最后两位数字将从每个组中截断,留下rgb值
c00000
,这是一种砖红色调颜色 .大多数浏览器只会忽略颜色字符串中的任何NON-hex值,用零替换非十六进制数字 .
ChuCknorris
转换为c00c0000000
. 此时,浏览器会将字符串分成三个相等的部分,指示红色,绿色和蓝色值:c00c 0000 0000
. 每个部分中的额外位将被忽略,这使得最终结果#c00000
是一个偏红的颜色 .注意,这不适用于符合CSS标准的CSS颜色解析 .
这是Netscape时代的延续:
它来自博客文章A little rant about Microsoft Internet Explorer's color parsing,它详细介绍了它,包括不同长度的颜色值等 .
如果我们依次从博客文章中应用规则,我们会得到以下信息:
这给出了以下结果:
这是一个演示
bgcolor
属性的示例,用于生成此"amazing"颜色样本:这也回答了问题的其他部分;为什么
bgcolor="chucknorr"
会产生黄色?好吧,如果我们应用规则,字符串是:这给出了淡黄色的金色 . 当字符串以9个字符开始时,我们这次保持第二个C,因此它最终成为最终的颜色值 .
当有人指出你可以做
color="crap"
时,我最初遇到了这个问题,而且,它出现了棕色 .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位整数 without checking for overflow . 只有八个十六进制数字适合32位整数,这就是为什么只考虑最后8个字符的原因 . 在将十六进制数字解析为32位整数之后,然后将它们除以16,将它们截断为8位整数,直到它们适合8位,这就是忽略前导零的原因 .
更新:此代码与规范中定义的内容不完全匹配,但唯一的区别是有几行代码 . 我认为这些线路被添加(在Netscape 4中):
原因是浏览器可以 not understand 它并尝试以某种方式将其转换为它可以理解的内容,在这种情况下转换为十六进制值!...
chucknorris
以c
开头,它是十六进制中的已识别字符,也是将所有无法识别的字符转换为0
!因此,十六进制格式的
chucknorris
变为:c00c00000000
,所有其他字符变为0
和c
仍然是它们的位置...现在他们被
RGB
(红色,绿色,蓝色)除以3 ......R: c00c, G: 0000, B:0000
...但是我们知道RGB的有效十六进制只有2个字符,意思是
R: c0, G: 00, B:00
所以真正的结果是:
我还添加了图像中的步骤作为快速参考:
chucknorris 是带有 c 的统计信息,浏览器读入十六进制值 .
浏览器
chucknorris
转换为c00c00000000
十六进制值 .然后
c00c00000000
十六进制值转换为 RGB 格式(除以3)浏览器只需要2位数字即可显示颜色 .
最后,在Web浏览器中显示
bgcolor = c00000
.这是一个展示的例子