Почему HTML считает «чакноррис» цветным? - PullRequest
7080 голосов
/ 30 ноября 2011

Почему некоторые случайные строки создают цвета, когда вводятся в качестве фона в HTML?Например:

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

... создает документ с красным фоном во всех браузерах и платформах.

Интересно, а chucknorri производита также красный фон chucknorr создает желтый фон.

Что здесь происходит?

Ответы [ 9 ]

6533 голосов
/ 01 декабря 2011

Это пережиток дней Netscape:

Пропущенные цифры рассматриваются как 0 [...].Неправильная цифра просто интерпретируется как 0. Например, значения # F0F0F0, F0F0F0, F0F0F, #FxFxFx и FxFxFx одинаковы.

Это из сообщения в блоге Небольшая болтовня о разборе цвета в Microsoft Internet Explorer , который подробно описывает его, в том числе различную длину значений цвета и т. Д.

Если мы применяем правила по очереди из сообщения в блоге, мыполучить следующее:

  1. Заменить все недопустимые шестнадцатеричные символы на 0 *

    chucknorris becomes c00c0000000
    
  2. Добавить к следующему общему количеству символов, кратному 3(11 -> 12)

    c00c 0000 0000
    
  3. Разделить на три равные группы, где каждый компонент представляет соответствующий компонент цвета цвета RGB:

    RGB (c00c, 0000, 0000)
    
  4. Усекать каждый аргумент справа вниз до двух символов

Что дает следующий результат:

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

Вот пример, демонстрирующий 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>

Это также отвечает на другую часть вопроса;почему bgcolor="chucknorr" дает желтый цвет?Хорошо, если мы применим правила, строка будет выглядеть так:

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

, которая дает светло-желтое золото.Поскольку строка начинается с 9 символов, мы сохраняем второй символ C на этот раз, следовательно, он заканчивается в конечном значении цвета.

Я первоначально столкнулся с этим, когда кто-то указал, что вы можете сделать color="crap", и, хорошополучается коричневый.

903 голосов
/ 17 октября 2012

Извините, что не согласен, но в соответствии с правилами синтаксического анализа устаревшего значения цвета, отправленного @ Yuhong Bao , chucknorris, НЕ равняется #CC0000, а скорее #C00000очень похожий, но немного другой оттенок красного.Я использовал Firefox ColorZilla , чтобы проверить это.

Состояние правил:

  • делает строку длиной, кратной 3, добавляя0s: chucknorris0
  • разделить строку на 3 строки одинаковой длины: chuc knor ris0
  • укоротить каждую строку до 2 символов: ch kn ri
  • сохранить шестнадцатеричные значения,и при необходимости добавьте 0: C0 00 00

Я смог использовать эти правила для правильной интерпретации следующих строк:

  • LuckyCharms
  • Luck
  • LuckBeALady
  • LuckBeALadyTonight
  • GangnamStyle

ОБНОВЛЕНИЕ: Оригинальные ответыкто сказал, что цвет #CC0000 с тех пор отредактировал свои ответы, чтобы включить исправление.

366 голосов
/ 30 ноября 2011

Большинство браузеров просто игнорируют любые не шестнадцатеричные значения в вашей цветовой строке, заменяя не шестнадцатеричные цифры нулями.

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>
272 голосов
/ 30 ноября 2013

Браузер пытается преобразовать chucknorris в шестнадцатеричный код цвета, потому что это недопустимое значение.

  1. В chucknorris все, кроме c, не является действительным шестнадцатеричным значением.
  2. Таким образом, он преобразуется в c00c00000000.
  3. Что становится # c00000 , оттенком красного.

Похоже, что это проблема в основном с Internet Explorer и Opera (12), так как Chrome (31) и Firefox (26) просто игнорируют это.

P.S. Цифры в скобках - это версии браузера, на которых я тестировал.

.

На светлой ноте

Чак Норрис не соответствует веб-стандартам. Веб-стандарты соответствуют Для него. # BADA55

225 голосов
/ 01 июля 2017

Причина в том, что браузер может не понять его и попытаться каким-то образом перевести его в то, что он может понять, и в данном случае в шестнадцатеричное значение! ...

chucknorris начинается с c, который является распознаваемым символом в шестнадцатеричном формате, а также преобразует все нераспознанные символы в 0!

Таким образом, chucknorris в шестнадцатеричном формате становится: c00c00000000, все остальные символы становятся 0, а c остается там, где они есть ...

Теперь они делятся на 3 для RGB (красный, зеленый, синий) ... R: c00c, G: 0000, B:0000 ...

Но мы знаем, что действительный шестнадцатеричный код для RGB составляет всего 2 символа, что означает R: c0, G: 00, B:00

Итак, реальный результат:

bgcolor="#c00000";

Я также добавил шаги на изображении в качестве краткого справочника для вас:

Why does HTML think “chucknorris” is a color?

207 голосов
/ 28 сентября 2012

Спецификация 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-разрядное целое число без проверки на переполнение .Только восемь шестнадцатеричных цифр помещаются в 32-разрядное целое число, поэтому учитываются только последние 8 символов.После разбора шестнадцатеричных чисел на 32-разрядные целые числа они затем усекаются до 8-разрядных целых чисел, деля их на 16, пока они не уместятся в 8-разрядные, поэтому ведущие нули игнорируются.

Обновление: этокод не совсем соответствует тому, что определено в спецификации, но единственное отличие состоит в том, что в нем есть несколько строк кода.Я думаю, что эти строки были добавлены (в Netscape 4):

if (bytes_per_val > 4)
{
      bytes_per_val = 4;
}
187 голосов
/ 24 мая 2016

Ответ:

  • Браузер попытается преобразовать chucknorris в шестнадцатеричное значение.
  • Поскольку c является единственным действительным шестнадцатеричным символом в chucknorris , значение превращается в: c00c00000000 ( 0 для всех недопустимых значений ).
  • Затем браузер делит результат на 3 группы: Red = c00c, Green = 0000, Blue = 0000.
  • Поскольку действительные шестнадцатеричные значения для фонов html содержат только 2 цифры для каждого типа цвета ( r , g , b ), последние 2 цифры усекаются из каждой группы, оставляя значение rgb c00000, цвета кирпично-красного тона.
12 голосов
/ 17 апреля 2018

chucknorris начинается с c , и браузер считывает его в шестнадцатеричное значение.

Поскольку 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.

Вот пример, демонстрирующий это:

<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>
7 голосов
/ 17 октября 2018

Правила для разбора цветов на унаследованных атрибутах включают в себя дополнительные шаги, чем те, которые упомянуты в существующих ответах.Компонент усечения до 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...