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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8318911/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-29 11:44:16  来源:igfitidea点击:

Why does HTML think “chucknorris” is a color?

htmlbrowserbackground-color

提问by user456584

How come certain random strings produce colors when entered as background colors in HTML? For example:

在 HTML 中作为背景颜色输入时,某些随机字符串如何产生颜色?例如:

<body bgcolor="chucknorris"> test </body>

...produces a document with a red backgroundacross all browsers and platforms.

...在所有浏览器和平台上生成具有红色背景的文档。

Interestingly, while chucknorriproduces a red background as well, chucknorrproduces a yellow background.

有趣的是,虽然chucknorri也会产生红色背景,但会chucknorr产生黄色背景。

What's going on here?

这里发生了什么?

采纳答案by dash

It's a holdover from the Netscape days:

这是网景时代的遗留物:

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.

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

It is from the blog post A little rant about Microsoft Internet Explorer's color parsingwhich covers it in great detail, including varying lengths of color values, etc.

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

If we apply the rules in turn from the blog post, we get the following:

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

  1. Replace all nonvalid hexadecimal characters with 0's

    chucknorris becomes c00c0000000
    
  2. Pad out to the next total number of characters divisible by 3 (11 -> 12)

    c00c 0000 0000
    
  3. Split into three equal groups, with each component representing the corresponding colour component of an RGB colour:

    RGB (c00c, 0000, 0000)
    
  4. Truncate each of the arguments from the right down to two characters

  1. 用 0 替换所有无效的十六进制字符

    chucknorris becomes c00c0000000
    
  2. 填充到下一个可被 3 整除的字符总数 (11 -> 12)

    c00c 0000 0000
    
  3. 分成三个相等的组,每个分量代表 RGB 颜色的相应颜色分量:

    RGB (c00c, 0000, 0000)
    
  4. 将每个参数从右边截断为两个字符

Which gives the following result:

这给出了以下结果:

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

Here's an example demonstrating the bgcolorattribute in action, to produce this "amazing" colour swatch:

这是一个演示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>

This also answers the other part of the question; why does bgcolor="chucknorr"produce a yellow colour? Well, if we apply the rules, the string is:

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

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

Which gives a light yellow gold colour. As the string starts off as 9 characters, we keep the second C this time around hence it ends up in the final colour value.

这给出了一种浅黄色的金色。由于字符串以 9 个字符开始,因此这次我们保留第二个 C,因此它以最终颜色值结束。

I originally encountered this when someone pointed out you could do color="crap"and, well, it comes out brown.

当有人指出你可以这样做时,我最初遇到了这个color="crap",好吧,它是棕色的。

回答by Jeremy Goodell

I'm sorry to disagree, but according to the rules for parsing a legacy color value posted by @Yuhong Bao, chucknorrisDOES NOT equate to #CC0000, but rather to #C00000, a very similar but slightly different hue of red. I used the Firefox ColorZilla add-onto verify this.

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

The rules state:

规则规定:

  • make the string a length that is a multiple of 3 by adding 0s: chucknorris0
  • separate the string into 3 equal length strings: chuc knor ris0
  • truncate each string to 2 characters: ch kn ri
  • keep the hex values, and add 0's where necessary: C0 00 00
  • 通过添加 0 使字符串长度为 3 的倍数: chucknorris0
  • 将字符串分成 3 个等长的字符串: chuc knor ris0
  • 将每个字符串截断为 2 个字符: ch kn ri
  • 保留十六进制值,并在必要时添加 0: C0 00 00

I was able to use these rules to correctly interpret the following strings:

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

  • LuckyCharms
  • Luck
  • LuckBeALady
  • LuckBeALadyTonight
  • GangnamStyle
  • LuckyCharms
  • Luck
  • LuckBeALady
  • LuckBeALadyTonight
  • GangnamStyle


UPDATE: The original answerers who said the color was #CC0000have since edited their answers to include the correction.

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

回答by Mike Christensen

Most browsers will simply ignore any NON-hex values in your color string, substituting non-hex digits with zeros.

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

ChuCknorristranslates to c00c0000000. At this point, the browser will divide the string into three equal sections, indicating Red, Greenand Bluevalues: c00c 0000 0000. Extra bits in each section will be ignored, which makes the final result #c00000which is a reddish color.

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

Note, this does notapply to CSS color parsing, which follow the CSS standard.

请注意,这并不能适用于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>

回答by aWebDeveloper

The browser is trying to convert chucknorrisinto hex colour code, because it's not a valid value.

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

  1. In chucknorris, everything except cis not a valid hex value.
  2. So it gets converted to c00c00000000.
  3. Which becomes #c00000, a shade of red.
  1. 在 中chucknorris,除了c不是有效的十六进制值之外的所有内容。
  2. 所以它被转换为c00c00000000.
  3. 它变成#c00000,一种红色。

This seems to be an issue primarily with Internet Explorerand Opera(12) as both Chrome (31) and Firefox (26) just ignore this.

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

P.S. The numbers in brackets are the browser versions I tested on.

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

.

.

On a lighter note

轻描淡写

Chuck Norris doesn't conform to web standards. Web standards conform to him. #BADA55

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

回答by Alireza

The reason is the browser can not understandit and try to somehow translate it to what it can understand and in this case into a hexadecimal value!...

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

chucknorrisstarts with cwhich is recognised character in hexadecimal, also it's converting all unrecognised characters into 0!

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

So chucknorrisin hexadecimal format becomes: c00c00000000, all other characters become 0and cremains where they are...

所以chucknorris在十六进制格式中变成: c00c00000000,所有其他字符变成0c保持它们原来的位置......

Now they get divided by 3 for RGB(red, green, blue)... R: c00c, G: 0000, B:0000...

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

But we know valid hexadecimal for RGB is just 2 characters, means R: c0, G: 00, B:00

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

So the real result is:

所以真正的结果是:

bgcolor="#c00000";

I also added the steps in the image as a quick reference for you:

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

Why does HTML think “chucknorris” is a colour?

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

回答by Yuhong Bao

The WHATWG HTML spec has the exact algorithm for parsing a legacy color value: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value

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

The code Netscape Classic used for parsing color strings is open source: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155

Netscape Classic 用于解析颜色字符串的代码开源:https: //dxr.mozilla.org/classic/source/lib/layout/layimage.c#155

For example, notice that each character is parsed as a hex digit and then is shifted into a 32-bit integer without checking for overflow. Only eight hex digits fit into a 32-bit integer, which is why only the last 8 characters are considered. After parsing the hex digits into 32-bit integers, they are then truncated into 8-bit integers by dividing them by 16 until they fit into 8-bit, which is why leading zeros are ignored.

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

Update: this code does not exactly match what is defined in the spec, but the only difference there is a few lines of code. I think it is these lines that was added (in Netscape 4):

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

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

回答by Webeng

Answer:

回答:

  • The browser will try to convert chucknorrisinto a hexadecimal value.
  • Since cis the only valid hex character in chucknorris, the value turns into: c00c00000000(0 for all values that were invalid).
  • The browser then divides the result into 3 groupds: Red = c00c, Green = 0000, Blue = 0000.
  • Since valid hex values for html backgrounds only contain 2 digits for each color type (r, g, b), the last 2 digits are truncated from each group, leaving an rgb value of c00000which is a brick-reddish toned color.
  • 浏览器会尝试将chucknorris转换为十六进制值。
  • 由于cchucknorris 中唯一有效的十六进制字符,因此该值变为:c00c000000000 表示所有无效值)。
  • 然后浏览器将结果分成 3 个组:Red = c00cGreen = 0000Blue = 0000
  • 由于 html 背景的有效十六进制值仅包含每种颜色类型(rgb)的 2 位数字,因此从每个组中截断最后 2 位数字,留下c00000砖红色调的 rgb 值。

回答by sameera lakshitha

chucknorrisstarts with c, and the browser reads it into a hexadecimal value.

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

Because A, B, C, D, E, and F are characters in hexadecimal.

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

The browser converts chucknorristo a hexadecimal value, C00C00000000.

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

Then the C00C00000000hexadecimal value is converted to RGBformat (divided by 3):

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

C00C00000000=> R:C00C, G:0000, B:0000

C00C00000000=> R:C00C, G:0000, B:0000

The browser needs only two digits to indicate the colour:

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

R:C00C, G:0000, B:0000=> R:C0, G:00, B:00=> C00000

R:C00C, G:0000, B:0000=> R:C0, G:00, B:00=>C00000

Finally, show bgcolor = C00000in the web browser.

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

Here's an example demonstrating it:

这是一个演示它的示例:

<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>

回答by Salman A

The rules for parsing colors on legacy attributesinvolves additional steps than those mentioned in existing answers. The truncate component to 2 digits part is described as:

解析旧属性颜色规则涉及比现有答案中提到的步骤更多的步骤。truncate 组件到 2 位部分描述为:

  1. Discard all characters except the last 8
  2. Discard leading zeros one by one as long as all components have a leading zero
  3. Discard all characters except the first 2
  1. 丢弃除最后 8 个字符以外的所有字符
  2. 只要所有组件都有前导零,就一一丢弃前导零
  3. 丢弃除前 2 个字符以外的所有字符

Some examples:

一些例子:

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

Below is a partial implementation of the algorithm. It does not handle errors or cases where the user enters a valid color.

下面是该算法的部分实现。它不处理错误或用户输入有效颜色的情况。

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%; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<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>&nbsp;</td>
      <td>&nbsp;</td>
    </tr>
    <tr>
      <td>&nbsp;</td>
      <td>&nbsp;</td>
    </tr>
  </tbody>
</table>