Comment se fait-il que certaines chaînes de caractères aléatoires produisent des couleurs lorsqu'elles sont saisies comme couleurs d'arrière-plan en HTML ? Par exemple :
<body bgcolor="chucknorris"> test </body>
...produit un document avec un fond rouge sur tous les navigateurs et toutes les plateformes.
Il est intéressant de noter que si chucknorri
produit également un fond rouge, chucknorr
produit un fond jaune.
Que se passe-t-il ici ?
C'est un vestige de l'époque de Netscape :
Les chiffres manquants sont traités comme des 0[...]. Un chiffre incorrect est simplement interprété comme 0. Par exemple, les valeurs #F0F0F0, F0F0F0, F0F0F, #FxFxFx et FxFxFx sont toutes identiques.
Ce texte est tiré de l'article du blog [A little rant about Microsoft Internet Explorer's color parsing][1] qui traite de ce sujet de manière très détaillée, notamment des différentes longueurs des valeurs de couleur, etc.
Si nous appliquons tour à tour les règles de l'article du blog, nous obtenons ce qui suit :
Remplacer tous les caractères hexadécimaux non valides par des 0.
chucknorris devient c00c0000000
Remplir jusqu'au prochain nombre total de caractères divisible par 3 (11 -> 12)
c00c 0000 0000
Divisez en trois groupes égaux, chaque composant représentant la composante correspondante d'une couleur RVB :
RVB (c00c, 0000, 0000)
Tronquez chacun des arguments en partant de la droite jusqu'à deux caractères
Ce qui donne le résultat suivant :
RGB (c0, 00, 00) = #C00000 or RGB(192, 0, 0)
Voici un exemple de l'utilisation de l'attribut bgcolor
pour produire cette "incroyable" palette de couleurs :
<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>
Cela répond également à l'autre partie de la question ; pourquoi bgcolor="chucknorr"
produit-il une couleur jaune ? Eh bien, si nous appliquons les règles, la chaîne de caractères est :
c00c00000 => c00 c00 000 => c0 c0 00 [RGB(192, 192, 0)]
Ce qui donne une couleur jaune or clair. Comme la chaîne commence par 9 caractères, nous gardons le deuxième C cette fois-ci et il se retrouve dans la valeur finale de la couleur.
J'ai rencontré ce problème à l'origine lorsque quelqu'un m'a fait remarquer que vous pouviez faire color="crap"
et, eh bien, cela donne du marron.
[1] : http://scrappy-do.blogspot.com/2004/08/little-rant-about-microsoft-internet.html
La plupart des navigateurs ignorent tout simplement les valeurs NON hexagonales dans votre chaîne de couleurs, remplaçant les chiffres non hexagonaux par des zéros.
ChuCknorris
se traduit par c00c0000000
. À ce stade, le navigateur va diviser la chaîne en trois sections égales, indiquant les valeurs Rouge, Vert et Bleu : c00c 0000 0000
. Les bits supplémentaires dans chaque section seront ignorés, ce qui donne le résultat final #c00000
qui est une couleur rougeâtre.
Notez que ceci ne s'applique pas à l'analyse des couleurs CSS, qui suit la norme 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>
La spécification HTML WHATWG contient l'algorithme exact pour analyser une valeur de couleur ancienne : https://html.spec.whatwg.org/multipage/infrastructure.html#rules-for-parsing-a-legacy-colour-value
Le code utilisé par Netscape Classic pour analyser les chaînes de couleur est une source ouverte : https://dxr.mozilla.org/classic/source/lib/layout/layimage.c#155
Par exemple, remarquez que chaque caractère est analysé en tant que chiffre hexadécimal, puis est décalé dans un entier de 32 bits sans vérification du débordement. Seuls huit chiffres hexadécimaux tiennent dans un entier de 32 bits, c'est pourquoi seuls les huit derniers caractères sont pris en compte. Après avoir analysé les chiffres hexadécimaux en nombres entiers de 32 bits, ils sont tronqués en nombres entiers de 8 bits en les divisant par 16 jusqu'à ce qu'ils tiennent dans 8 bits, c'est pourquoi les zéros de tête sont ignorés.
Mise à jour : ce code ne correspond pas exactement à ce qui est défini dans la spécification, mais la seule différence réside dans quelques lignes de code. Je pense que ce sont ces lignes qui ont été ajoutées (dans Netscape 4) :
if (bytes_per_val > 4)
{
bytes_per_val = 4;
}