为什么 HTML 认为“chucknorris”是一种颜色?

html browser background-color

为什么某些随机字符串在 HTML 中作为背景颜色输入时会产生颜色?

例如,bgcolor="chucknorris" 产生 红色背景

测试

相反,bgcolor="chucknorr" 会产生黄色背景

测试

这适用于各种浏览器和平台。这里发生了什么?

我不得不(因为我怎么可能不这样做)所以我运行了 an entire dictionary through a script and rendered it out as a table - 是的,whippersnappers 绝对是一个有效的颜色代码。

这个问题在播客 CoRecursive 中被引用,在 2022-01 episode 中,大约 34 分 35 秒。虽然引用的答案和评论确实 not 似乎在这里(包括已删除的答案)。 这个问题(除非有另一个具有相同措辞的问题)。

@mindplay.dk 目前因依赖错误源源不断而失败。

i
ib.

这是 Netscape 时代的遗留物:

缺少的数字被视为 0[...]。错误的数字被简单地解释为 0。例如,#F0F0F0、F0F0F0、F0F0F、#FxFxFx 和 FxFxFx 的值都是相同的。

它来自博客文章A little rant about Microsoft Internet Explorer's color parsing,其中详细介绍了它,包括不同长度的颜色值等。

如果我们从博客文章中依次应用规则,我们会得到以下信息:

用 0 替换所有无效的十六进制字符:chucknorris 变为 c00c0000000 填充到下一个可被 3 整除的字符总数(11 → 12):c00c 0000 0000 分成三个相等的组,每个分量代表 RGB 颜色的相应颜色分量: RGB (c00c, 0000, 0000) 将每个参数从右截断为两个字符。

最后,给出以下结果:

RGB (c0, 00, 00) = #C00000 or RGB(192, 0, 0)

下面是一个示例,展示了 bgcolor 属性的作用,以生成这个“惊人的”色样:

< /tr>
chuck norris T先生 ninjaturtle
sick 废话

这也回答了问题的另一部分:为什么 bgcolor="chucknorr" 会产生黄色?好吧,如果我们应用规则,字符串是:

c00c00000 => c00 c00 000 => c0 c0 00 [RGB(192, 192, 0)]

呈现出淡黄色的金色。由于字符串以 9 个字符开始,所以这次我们保留了第二个“C”,因此它以最终颜色值结束。

当有人指出你可以做 color="crap" 时,我最初遇到这种情况,而且,它是棕色的。

有趣的事实 - 根据这个逻辑,那么 test 会给你加州出租车的颜色! Netscape 的总部位于加利福尼亚州的山景城!

有趣的事实 #2 - CharmeleonIvysaurSquirtle 将分别产生红色、绿色和蓝色。

这里的想法是,如果您是某个未来社会的程序员,使用每种颜色 16 位,现在的浏览器会将它们截断为最重要的 8 位?

J
Jeremy Goodell

很抱歉不同意,但根据解析 @Yuhong Bao 发布的旧颜色值的规则,chucknorris 不等同于 #CC0000,而是等同于 #C00000,一种非常相似但略有不同的色调红色的。我使用 Firefox ColorZilla add-on 来验证这一点。

规则规定:

通过添加 0 使字符串的长度为 3 的倍数:chucknorris0

将字符串分成 3 个相等长度的字符串:chuc knor ris0

将每个字符串截断为 2 个字符:ch kn ri

保留十六进制值,并在必要时添加 0:C0 00 00

我能够使用这些规则来正确解释以下字符串:

幸运符

运气

幸运女神

幸运女神今晚

江南Style

更新:说颜色是 #CC0000 的原始回答者已经编辑了他们的答案以包括更正。

A
Alireza

原因是浏览器无法理解它并尝试以某种方式将其转换为它可以理解的内容,在这种情况下转换为十六进制值!...

chucknorrisc 开头,它是十六进制的可识别字符,它还将所有无法识别的字符转换为 0

因此,十六进制格式的 chucknorris 变为:c00c00000000,所有其他字符变为 0,而 c 保持在原来的位置......

现在它们除以 3 得到 RGB(红色、绿色、蓝色)... R: c00c, G: 0000, B:0000...

但我们知道 RGB 的有效十六进制只有 2 个字符,表示 R: c0, G: 00, B:00

所以真正的结果是:

bgcolor="#c00000";

我还添加了图像中的步骤作为您的快速参考:

https://i.stack.imgur.com/sc8bX.jpg

我喜欢这幅画:)

M
Mike Christensen

大多数浏览器会简单地忽略颜色字符串中的任何非十六进制值,用零替换非十六进制数字。

ChuCknorris 转换为 c00c0000000。此时,浏览器会将字符串分成三个相等的部分,分别表示RedGreenBlue的值:c00c 0000 0000。每个部分中的额外位将被忽略,这使得最终结果 #c00000 呈红色。

请注意,这不适用于遵循 CSS 标准的 CSS 颜色解析。

Redish

同上

黑色

You might consider editing your answer, because the <font> element is hereby obsolete by HTML5.

i
ib.

浏览器正在尝试将 chucknorris 转换为十六进制颜色代码,因为它不是有效值。

在chucknorris 中,除了c 之外的所有内容都不是有效的十六进制值。所以它被转换为c00c00000000。变成#c00000,一个红色的阴影。

这似乎主要是 Internet Explorer 和 Opera (12) 的问题,因为 Chrome (31) 和 Firefox (26) 都忽略了这一点。

PS 括号中的数字是我测试的浏览器版本。

在一个较轻的音符上

Chuck Norris 不符合网络标准。网络标准符合他。 #BADA55

我已经在 Firefox 26 上对此进行了测试并且它有效,所以我不相信你的参考是正确的。同样从以下链接scrappy-do.blogspot.com/2004/08/…,您会看到它是从 Netscape 继承的,因此它不是 Internet Explorer 或 Opera 特有的!

Y
Yuhong Bao

WHATWG HTML 规范具有解析旧颜色值的准确算法:https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value

用于解析颜色字符串的 Netscape Classic 代码是开源代码:https://github.com/zii/netscape/blob/master/lib/layout/layimage.c#L150

例如,请注意每个字符都被解析为一个十六进制数字,然后被移入一个 32 位整数而不检查溢出。只有八个十六进制数字适合 32 位整数,这就是为什么只考虑最后 8 个字符的原因。将十六进制数字解析为 32 位整数后,然后通过将它们除以 16 将它们截断为 8 位整数,直到它们适合 8 位,这就是忽略前导零的原因。

更新:此代码与规范中定义的不完全匹配,但唯一的区别是几行代码。我认为添加的是 these lines(在 Netscape 4 中):

if (bytes_per_val > 4)
{
    bytes_per_val = 4;
}
a
arkon

回答:

浏览器将尝试将chucknorris 转换为十六进制值。

由于c 是chucknorris 中唯一有效的十六进制字符,因此该值变为:c00c00000000(所有无效值均为0)。

然后浏览器将结果分为 3 组:红色 = c00c、绿色 = 0000、蓝色 = 0000。

由于 html 背景的有效十六进制值仅包含每种颜色类型(r、g、b)的 2 位数字,因此从每个组中截断最后 2 位数字,留下 rgb 值 c00000,它是砖红色调的颜色。

i
ib.

chucknorrisc 开头,浏览器将其读入十六进制值。

因为 A、B、C、D、E 和 F 是十六进制字符。

浏览器将 chucknorris 转换为十六进制值 C00C00000000

然后将 C00C00000000 十六进制值转换为 RGB 格式(除以 3):

C00C00000000 ⇒ R:C00C, G:0000, B:0000

浏览器只需要两位数字来指示颜色:

R:C00C, G:0000, B:0000 ⇒ R:C0, G:00, B:00 ⇒ C00000

最后,在网络浏览器中显示 bgcolor = C00000

这是一个演示它的示例:

chucknorris c00c00000000 c00000

S
Salman A

rules for parsing colors on legacy attributes 涉及的步骤比现有答案中提到的步骤多。将部分截断为 2 位的部分描述为:

丢弃除最后 8 个以外的所有字符 只要所有组件都有前导零,就一个一个丢弃前导零 丢弃除前 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: 如果输入为 "" 则返回错误 input = input.trim(); // todo: 如果输入为“透明”则返回错误 // todo: 如果输入是指定颜色则返回对应的#rrggbb // todo: 如果输入匹配则返回#rrggbb #rgb // todo: 替换大于 U+ 的 unicode 代码点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", 输入); $cells.eq(1).attr("bgcolor", color); var color1 = $cells.eq (0).css("背景颜色"); var color2 = $cells.eq(1).css("背景颜色"); $cells.eq(2).empty().append("bgcolor: " + input, "
", "getComputedStyle: " + color1); $cells.eq(3).empty().append("bgcolor: " + color, "
", "getComputedStyle: " +颜色2); }); });正文 {字体:中等等宽; } 输入 { 宽度:20em; } 表 { 表布局:固定;宽度:100%; }

< /tr>
Left Color Right Color
   
   

M
Muhammad Ali

用简单的话回答:

简短的回答是,HTML 渴望取悦并且基本上会接受你给它的任何东西。 HTML 是围绕故意忽略格式错误的输入而构建的。

整体概念:

HTML 接受非十六进制字符为 0,所以我们都知道 0-9 定义 0 到 9,然后 AF 定义 10 到 15。所以有很多单词可以是像“chucknorris”这样的颜色,像这样的深血红色。同样,“stevensegal”的意思是绿色。

显示意外的颜色:如果您在 bgcolor 中输入任何包含一些十六进制字符的单词,那么该字符将向您显示一些您从未想象过的意外颜色。它就像#F00F00 等于#FotFot 一样工作。但这仅适用于表格标签内的 bgcolor ,其他任何地方都没有。

演示:

为什么 HTML 认为 Chucknorris 是颜色?

这里是实现...!!!

颜色是:
chucknorris