Ako je možné, že niektoré náhodné reťazce vytvárajú farby, keď sú zadané ako farby pozadia v jazyku HTML? Napríklad:
<body bgcolor="chucknorris"> test </body>
...vytvorí dokument s červeným pozadím vo všetkých prehliadačoch a platformách.
Zaujímavé je, že zatiaľ čo chucknorri
vytvára aj červené pozadie, chucknorr
vytvára žlté pozadie.
Čo sa tu deje?
Je to pozostatok z čias spoločnosti Netscape:
Chýbajúce číslice sa považujú za 0[...]. Nesprávna číslica sa jednoducho interpretuje ako 0. Napríklad hodnoty #F0F0F0, F0F0F0, F0F0F, #FxFxFx a FxFxFx sú všetky rovnaké.
Je to z príspevku na blogu A little rant about Microsoft Internet Explorer's color parsing, ktorý sa tomu venuje veľmi podrobne, vrátane rôznych dĺžok hodnôt farieb atď.
Ak postupne aplikujeme pravidlá z príspevku na blogu, dostaneme nasledovné:
Nahraďte všetky neplatné hexadecimálne znaky číslicami 0's
z chucknorris sa stane c00c0000000
Doplňte na najbližší celkový počet znakov deliteľný 3 (11 -> 12)
c00c 0000 0000
Rozdeľte na tri rovnaké skupiny, pričom každá zložka predstavuje príslušnú farebnú zložku farby RGB:
RGB (c00c, 0000, 0000)
Skráťte každý z argumentov sprava na dva znaky
Čo dáva nasledujúci výsledok:
RGB (c0, 00, 00) = #C00000 or RGB(192, 0, 0)
Tu'je príklad demonštrujúci atribút bgcolor
v akcii, ktorý vytvára tento "úžasný" farebný vzorník:
<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>
Toto je aj odpoveď na druhú časť otázky; prečo bgcolor="chucknorr"
vytvára žltú farbu? No, ak použijeme pravidlá, reťazec je:
c00c00000 => c00 c00 000 => c0 c0 00 [RGB(192, 192, 0)]
Čo dáva svetložltú zlatú farbu. Keďže reťazec začína ako 9 znakov, druhé C tentoraz ponecháme, preto sa dostane do konečnej hodnoty farby.
Pôvodne som sa s tým stretol, keď ma niekto upozornil, že môžete urobiť color="crap"
a, nuž, vyjde to hnedé.
Väčšina prehliadačov bude jednoducho ignorovať všetky hodnoty, ktoré nie sú hexadecimálne, vo vašom farebnom reťazci a nahradí ich nulami.
ChuCknorris
sa prekladá ako c00c0000000
. V tomto okamihu prehliadač rozdelí reťazec na tri rovnaké časti označujúce hodnoty červená, zelená a modrá: c00c 0000 0000
. Dodatočné bity v každej časti sa budú ignorovať, čím vznikne konečný výsledok #c00000
, ktorý má červenú farbu.
Všimnite si, že sa to nevzťahuje na rozbor farieb CSS, ktoré sa riadia štandardom 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>
Špecifikácia WHATWG HTML obsahuje presný algoritmus na analýzu staršej hodnoty farby: https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value
Kód Netscape Classic používaný na parsovanie farebných reťazcov je otvorený: https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155
Všimnite si napríklad, že každý znak sa analyzuje ako šestnástková číslica a potom sa posunie do 32-bitového celého čísla bez kontroly pretečenia. Do 32-bitového celého čísla sa zmestí len osem hexadecimálnych číslic, preto sa berie do úvahy len posledných 8 znakov. Po rozbore hexadecimálnych číslic na 32-bitové celé čísla sa potom skrátia na 8-bitové celé čísla delením 16, kým sa nezmestia do 8-bitového čísla, preto sa ignorujú úvodné nuly.
Aktualizácia: tento kód sa presne nezhoduje s tým, čo je definované v špecifikácii, ale jediný rozdiel je v niekoľkých riadkoch kódu. Myslím, že práve tieto riadky boli pridané (v Netscape 4):
if (bytes_per_val > 4)
{
bytes_per_val = 4;
}