Why does HTML think “chucknorris” is a color?

后端 未结 9 1915
醉梦人生
醉梦人生 2020-11-22 05:07

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

相关标签:
9条回答
  • 2020-11-22 05:21

    The browser is trying to convert chucknorris into hex colour code, because it’s not a valid value.

    1. In chucknorris, everything except c is not a valid hex value.
    2. So it gets converted to c00c00000000.
    3. Which becomes #c00000, a shade of red.

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

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

    On a lighter note

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

    0 讨论(0)
  • 2020-11-22 05:22

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

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

    The browser converts chucknorris to a hexadecimal value, C00C00000000.

    Then the C00C00000000 hexadecimal value is converted to RGB format (divided by 3):

    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

    Finally, show bgcolor = C00000 in the web browser.

    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>

    0 讨论(0)
  • 2020-11-22 05:26

    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.

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

    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.

    Which, finally, gives the following result:

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

    Here’s an example demonstrating the bgcolor attribute in action, to produce this “amazing” colour swatch:

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

    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.

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

    0 讨论(0)
  • 2020-11-22 05:31

    Answer:

    • The browser will try to convert chucknorris into a hexadecimal value.
    • Since c is 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 c00000 which is a brick-reddish toned color.
    0 讨论(0)
  • 2020-11-22 05:36

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

    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

    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>

    0 讨论(0)
  • 2020-11-22 05:37

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

    chucknorris starts with c which is recognised character in hexadecimal, also it's converting all unrecognised characters into 0!

    So chucknorris in hexadecimal format becomes: c00c00000000, all other characters become 0 and c remains where they are...

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

    But we know valid hexadecimal for RGB is just 2 characters, means 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:

    0 讨论(0)
提交回复
热议问题