Wie kommt es, dass bestimmte zufällige Zeichenfolgen Farben erzeugen, wenn sie in HTML als Hintergrundfarben eingegeben werden? Zum Beispiel:
<body bgcolor="chucknorris"> test </body>
... erstellt ein Dokument mit einem roter Hintergrund in allen Browsern und Plattformen.
Während chucknorri
ebenfalls einen roten Hintergrund erzeugt, erzeugt chucknorr
interessanterweise einen gelben Hintergrund.
Was ist hier los?
Es ist ein Überbleibsel aus den Netscape-Tagen:
Fehlende Ziffern werden als 0 [...] behandelt. Eine falsche Ziffer wird einfach als 0 interpretiert. Zum Beispiel sind die Werte # F0F0F0, F0F0F0, F0F0F, #FxFxFx und FxFxFx alle gleich.
Es ist aus dem Blog-Beitrag Ein wenig über die Farbanalyse von Microsoft Internet Explorer gestritten, der es ausführlich behandelt, einschließlich unterschiedlicher Längen von Farbwerten usw.
Wenn wir die Regeln der Reihe nach aus dem Blog-Post übernehmen, erhalten wir Folgendes:
Ersetzen Sie alle nicht gültigen Hexadezimalzeichen durch Nullen
chucknorris becomes c00c0000000
Auf die nächste Gesamtzahl der durch 3 teilbaren Zeichen auffüllen (11 -> 12)
c00c 0000 0000
In drei gleiche Gruppen aufgeteilt, wobei jede Komponente die entsprechende Farbkomponente einer RGB-Farbe darstellt:
RGB (c00c, 0000, 0000)
Kürzen Sie jedes der Argumente von rechts nach unten auf zwei Zeichen
Was das folgende Ergebnis ergibt:
RGB (c0, 00, 00) = #C00000 or RGB(192, 0, 0)
Hier ist ein Beispiel, das das bgcolor
-Attribut in Aktion demonstriert, um dieses "erstaunliche" Farbmuster zu erzeugen:
<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>
Dies beantwortet auch den anderen Teil der Frage; Warum erzeugt bgcolor="chucknorr"
eine gelbe Farbe? Nun, wenn wir die Regeln anwenden, lautet die Zeichenfolge:
c00c00000 => c00 c00 000 => c0 c0 00 [RGB(192, 192, 0)]
Das ergibt eine hellgelbe Goldfarbe. Da die Zeichenfolge mit 9 Zeichen beginnt, wird das zweite C dieses Mal beibehalten, sodass es im endgültigen Farbwert endet.
Ich bin ursprünglich darauf gestoßen, als jemand darauf hingewiesen hat, dass Sie color="crap"
ausführen können, und nun, es kommt braun heraus.
Es tut mir leid, dass ich nicht damit einverstanden bin, aber gemäß den Regeln zum Parsen eines von @ Yuhong Bao geposteten Legacy-Farbwerts entspricht chucknorris
NICHT #CC0000
, sondern #C00000
, eine sehr ähnliche, aber leicht abweichende rote Farbe. Ich habe das Firefox ColorZilla Add-On verwendet, um dies zu überprüfen.
Die Regeln besagen:
chucknorris0
chuc knor ris0
ch kn ri
C0 00 00
Ich konnte diese Regeln verwenden, um die folgenden Zeichenfolgen korrekt zu interpretieren:
LuckyCharms
Luck
LuckBeALady
LuckBeALadyTonight
GangnamStyle
UPDATE: Die ursprünglichen Antwortenden, die sagten, dass die Farbe #CC0000
war, haben ihre Antworten seitdem bearbeitet, um die Korrektur einzuschließen.
Die meisten Browser ignorieren einfach alle Nicht-Hex-Werte in Ihrer Farbzeichenfolge und ersetzen Nicht-Hex-Ziffern durch Nullen.
ChuCknorris
übersetzt in c00c0000000
. Zu diesem Zeitpunkt teilt der Browser die Zeichenfolge in drei gleiche Abschnitte auf, die die Werte Rot, Grün und Bla angeben: c00c 0000 0000
. Zusätzliche Bits in jedem Abschnitt werden ignoriert, wodurch das Endergebnis #c00000
eine rötliche Farbe erhält.
Beachten Sie, dass dies nicht für die CSS-Farbanalyse gilt, die dem CSS-Standard folgt.
<p><font color='chucknorris'>Redish</font></p>
<p><font color='#c00000'>Same as above</font></p>
<p><span style="color: chucknorris">Black</span></p>
Der Browser versucht, chucknorris
in hexadezimalen Farbcode umzuwandeln, da es sich nicht um einen gültigen Wert handelt.
chucknorris
ist alles außer c
kein gültiger hexadezimaler Wert.c00c00000000
konvertiert.Dies scheint vor allem bei Internet Explorer und Opera (12) ein Problem zu sein, da sowohl Chrome (31) als auch Firefox (26) dies einfach ignorieren.
P.S. Die Zahlen in Klammern sind die Browserversionen, auf denen ich getestet habe.
.
Leichter gesagt
Chuck Norris entspricht nicht den Webstandards. Webstandards entsprechen ihm. # BADA55
Der Grund ist, dass der Browser es nicht verstehen kann und versucht, es irgendwie in das zu übersetzen, was er verstehen kann und in diesem Fall in einen hexadezimalen Wert! ...
chucknorris
beginnt mit c
, das als Hexadezimalzeichen erkannt wird. Außerdem werden alle nicht erkannten Zeichen in 0
konvertiert.
So wird chucknorris
im hexadezimalen Format zu: c00c00000000
, alle anderen Zeichen werden 0
und c
verbleiben dort, wo sie sich befinden ...
Jetzt werden sie durch 3 geteilt für RGB
(rot, grün, blau) ... R: c00c, G: 0000, B:0000
...
Wir wissen jedoch, dass eine gültige Hexadezimalzahl für RGB nur 2 Zeichen beträgt, dh R: c0, G: 00, B:00
.
Das eigentliche Ergebnis ist also:
bgcolor="#c00000";
Ich habe auch die Schritte im Bild als Kurzreferenz für Sie hinzugefügt:
Die WHATWG-HTML-Spezifikation enthält den genauen Algorithmus zum Parsen eines älteren Farbwerts: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value
Der zum Parsen von Farbzeichenfolgen verwendete Code Netscape Classic ist Open Source: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155
Beachten Sie beispielsweise, dass jedes Zeichen als Hexadezimalzahl analysiert und dann in eine 32-Bit-Ganzzahl verschoben wird, ohne auf Überlauf zu prüfen . In eine 32-Bit-Ganzzahl passen nur acht Hexadezimalziffern, weshalb nur die letzten 8 Zeichen berücksichtigt werden. Nach dem Parsen der Hexadezimalziffern in 32-Bit-Ganzzahlen werden diese durch Teilen durch 16 in 8-Bit-Ganzzahlen gekürzt, bis sie in 8-Bit passen. Deshalb werden führende Nullen ignoriert.
Update: Dieser Code stimmt nicht genau mit der Definition in der Spezifikation überein, aber der einzige Unterschied sind einige Codezeilen. Ich denke, es sind diese Zeilen, die hinzugefügt wurden (in Netscape 4):
if (bytes_per_val > 4)
{
bytes_per_val = 4;
}
Antwort:
c
das einzige gültige Hex-Zeichen in chucknorris ist, wird der Wert zu: c00c00000000
(für alle ungültigen Werte).Red = c00c
, Green = 0000
, Blue = 0000
.c00000
übrig bleibt, der eine ziegelrötlich getönte Farbe ist.chucknorris beginnt mit c und wird vom Browser hexadezimal gelesen .
Weil A, B, C, D, E und F hexadezimale Zeichen sind.
Der Browser konvertiert chucknorris
in einen hexadezimalen Wert, C00C00000000
.
Dann wird der Hexadezimalwert C00C00000000
in das Format RGB konvertiert (geteilt durch 3):
C00C00000000
=>R:C00C, G:0000, B:0000
Der Browser benötigt nur zwei Ziffern, um die Farbe anzuzeigen:
R:C00C, G:0000, B:0000
=>R:C0, G:00, B:00
=>C00000
Zeigen Sie abschließend im Webbrowser bgcolor = C00000
an.
Hier ist ein Beispiel, das dies demonstriert:
<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>
Das Regeln für das Parsen von Farben in Legacy-Attributen umfasst zusätzliche Schritte als die in vorhandenen Antworten genannten. Der Anteil der Kürzung auf 2 Stellen wird wie folgt beschrieben:
Einige Beispiele:
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
Unten sehen Sie eine teilweise Implementierung des Algorithmus. Es behandelt keine Fehler oder Fälle, in denen der Benutzer eine gültige Farbe eingibt.
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> </td>
<td> </td>
</tr>
<tr>
<td> </td>
<td> </td>
</tr>
</tbody>
</table>