div - html text color




為什麼HTML認為“chucknorris”是一種顏色? (6)

WHATWG HTML規範具有解析遺留顏色值的確切算法: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-valuehttps://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#155https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155

例如,請注意每個字符都被解析為十六進制數字,然後轉換為32位整數而不檢查溢出 。 只有八個十六進制數字適合32位整數,這就是為什麼只考慮最後8個字符的原因。 在將十六進制數字解析為32位整數之後,然後將它們除以16,將它們截斷為8位整數,直到它們適合8位,這就是忽略前導零的原因。

更新:此代碼與規範中定義的內容不完全匹配,但唯一的區別是幾行代碼。 我認為這些線路被添加(在Netscape 4中):

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

當在HTML中作為背景顏色輸入時,某些隨機字符串如何產生顏色? 例如:

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

...在所有瀏覽器和平台上生成一個紅色背景的文檔。

有趣的是,雖然chucknorri產生紅色背景,但chucknorr產生黃色背景。

這裡發生了什麼?


解析遺留屬性上的顏色規則涉及比現有答案中提到的步驟更多的步驟。 截斷組件為2位數部分描述為:

  1. 丟棄除最後8個之外的所有字符
  2. 只要所有組件都具有前導零 ,就逐個丟棄前導零
  3. 丟棄除前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>


回答:

  • 瀏覽器將嘗試將chucknorris轉換為十六進制值。
  • 由於cchucknorris中唯一有效的十六進製字符, 因此該值變為: c00c00000000對於所有無效的值,為0 )。
  • 然後瀏覽器將結果分為3個分組: Red = c00cGreen = 0000Blue = 0000
  • 由於html背景的有效十六進制值僅包含每種顏色類型( rgb )的2位數字,因此最後兩位數字將從每個組中截斷,留下rgb值c00000 ,這是一種磚紅色調顏色。

原因是瀏覽器無法理解它並嘗試以某種方式將其轉換為它能理解的內容,在這種情況下轉換為十六進制值!...

chucknorrisc開頭,它是十六進制中識別的字符,也是將所有未識別的字符轉換為0

因此,十六進制格式的c00c00000000變為: c00c00000000 ,所有其他字符變為0c保持c00c00000000 ...

現在他們將RGB除以3(紅色,綠色,藍色)...... R: c00c, G: 0000, B:0000 ......

但我們知道RGB的有效十六進制只有2個字符,意味著R: c0, G: 00, B:00

所以真正的結果是:

bgcolor="#c00000";

我還添加了圖像中的步驟作為快速參考:


我很抱歉不同意,但根據解析@Yuhong Bao發布的遺留顏色值的規則, chucknorris並不等同於#CC0000 ,而是#C00000 ,一種非常相似但略有不同的紅色色調。 我使用Firefox ColorZilla插件來驗證這一點。

規則規定:

  • 通過添加0來使字符串的長度為3的倍數: chucknorris0
  • 將字符串分成3個相等長度的字符串: chuc knor ris0
  • 將每個字符串截斷為2個字符: ch kn ri
  • 保留十六進制值,並在必要時添加0: C0 00 00

我能夠使用這些規則來正確解釋以下字符串:

  • LuckyCharms
  • Luck
  • LuckBeALady
  • LuckBeALadyTonight
  • GangnamStyle

更新: 原來的回答說,顏色是#CC0000已經編輯了他們的答案,包括更正。


瀏覽器正在嘗試將chucknorris轉換為十六進制顏色代碼,因為它不是有效值。

  1. chucknorris ,除c之外的所有內容都不是有效的十六進制值。
  2. 所以它被轉換為c00c00000000
  3. 哪個變成了#c00000 ,一個紅色的陰影。

這似乎主要是Internet ExplorerOpera (12)的問題,因為Chrome(31)和Firefox(26)都忽略了這一點。

PS括號中的數字是我測試的瀏覽器版本。

更輕鬆的說明

查克諾里斯不符合網絡標準。 Web標準符合他的要求。 #BADA55





background-color