首页 文章

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

提问于
浏览
6746

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

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

...在所有浏览器和平台上生成一个包含 red background 的文档 .

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

这里发生了什么?

9 回答

  • 195

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

    • chucknorris 中,除 c 之外的所有内容都不是有效的十六进制值 .

    • 因此它被转换为 c00c00000000 .

    • 哪个成为 #c00000 ,一片红色 .

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

    附:括号中的数字是我测试的浏览器版本 .

    .

    更轻松的说明

    查克诺里斯不符合网络标准 . Web标准符合他的要求 . #BADA55

  • 853

    rules for parsing colors on legacy attributes涉及的步骤不同于现有答案中提到的步骤 . 截断组件为2位数部分描述为:

    • 丢弃除最后8个之外的所有字符

    • 逐个丢弃前导零 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%; }
    
    <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>
    
  • 345

    我很抱歉不同意,但根据解析@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 已经编辑了他们的答案,包括更正 .

  • 237

    Answer:

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

    • 由于 cchucknorris 中唯一有效的十六进制字符,因此该值将变为: c00c000000000 for all values that were invalid ) .

    • 浏览器然后将结果分为3个分组: Red = c00cGreen = 0000Blue = 0000 .

    • 由于html背景的有效十六进制值仅包含每种颜色类型( rgb )的2位数字,因此最后两位数字将从每个组中截断,留下rgb值 c00000 ,这是一种砖红色调颜色 .

  • 158

    大多数浏览器只会忽略颜色字符串中的任何NON-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>
    
  • 6223

    这是Netscape时代的延续:

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

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

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

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

    这给出了以下结果:

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

    这是一个演示 bgcolor 属性的示例,用于生成此"amazing"颜色样本:

    <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" 时,我最初遇到了这个问题,而且,它出现了棕色 .

  • 173

    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中):

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

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

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

    因此,十六进制格式的 chucknorris 变为: c00c00000000 ,所有其他字符变为 0c 仍然是它们的位置...

    现在他们被 RGB (红色,绿色,蓝色)除以3 ...... R: c00c, G: 0000, B:0000 ...

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

    所以真正的结果是:

    bgcolor="#c00000";
    

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

  • 0

    chucknorris 是带有 c 的统计信息,浏览器读入十六进制值 .

    因为a,b,c,d,e,f是十六进制的字符

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

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

    c00c00000000 => R:c00c,G:0000,B:0000

    浏览器只需要2位数字即可显示颜色 .

    R:c00c,G:0000,B:0000 => R:c0,G:00,B:00 => c00000

    最后,在Web浏览器中显示 bgcolor = c00000 .

    这是一个展示的例子

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

相关问题