Почему HTML считает «чакноррис» цветным?

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

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

Всего 9 ответов


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

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

Это из поста в блоге который подробно описывает его, в том числе различную длину значений цвета и т. Д.

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

  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 в действии, чтобы создать этот «удивительный» образец цвета:

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

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

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

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


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

Правила гласят:

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

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

  • LuckyCharms
  • Luck
  • LuckBeALady
  • LuckBeALadyTonight
  • GangnamStyle

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


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

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> 


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

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

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

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

,

На более легкой ноте

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


HTML-спецификация WHATWG имеет точный алгоритм анализа устаревшего значения цвета: 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;
}

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

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

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

Почему HTML считает «чакноррис» цветным?


Ответ:

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

chucknorris - это статистика, в которой браузер считывает шестнадцатеричное значение.

потому что 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

наконец, покажите 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> 


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

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


Есть идеи?

10000