Mes impressions sur le web, les standards et autres…


Bugs en série - suite

Continuant mon voyage fantastique au pays des bugs, je m’en vais maintenant vous relater comment je me suis trouvé aux prises avec deux bugs CSS teigneux, l’un affectant Safari, l’autre, beaucoup plus vicieux, continue de me résister et affecte selon les cas au moins Opera et Firefox.

Safari et styles de sélection de texte

J’applique les styles suivants sur tous les éléments de la page et, notamment, sur des paragraphes dont le contenu est justifié (text-align: justify;) :

*::selection { background-color: une_couleur; color: autre_couleur; }
*::-moz-selection { background-color: une_couleur; color: autre_couleur; }

Résultat sur Safari 2.0 (cliquez sur les images pour les voir grandeur réelle) :
Lorsque l’utilisateur sélectionne du texte, celui-ci part en sucette
Lorsque l’utilisateur sélectionne du texte, celui-ci part en sucette

Safari a manifestement quelques problèmes pour gérer et la justification de texte et les styles CSS sur la sélection de celui-ci.

J’ai d’abord fait quelques recherches sur l’existence éventuelle d’un pseudo-élément ::-khtml-selection, ce qui m’aurait permis d’annuler ces styles de sélection uniquement pour les navigateurs basés sur KHTML (pour peu que les mots-clés CSS nécessaires fussent gérés aussi par KHTML) :

*::selection { background-color: une_couleur; color: autre_couleur; }
*::-moz-selection { background-color: une_couleur; color: autre_couleur; }
*::-khtml-selection { background-color: Highlight; color: HighlightText; }

Mais ce pseudo-élément n’existe apparamment pas. Étant donné que je me posais déjà la question de savoir si la justification de texte était adaptée pour un rendu à l’écran, ce bug n’a fait que me pousser à prendre la décision de retourner au plus raisonnable text-align: left;.

Feuilles de styles et encodage

Tout est parti d’un bug de Safari lié à la génération de contenu. Voici la règle CSS en cause (vous pouvez en voir le résultat dans Firefox, Opera et Safari dans le billet précédent) :

table td[scope="row"]::after { content: "\00A0»"; }

Safari affiche donc » au lieu d’afficher  » (le guillemet fermant est précédé d’une espace insécable). J’ai d’abord simplement pensé sans réfléchir que Safari ignore simplement le paramètre charset de l’en-tête HTTP Content-Type et utilise le jeu de caractère ISO-8859-1 pour les feuilles de styles. En fait, ça semble être un plus tordu.

Mon hypothèse est la suivante : Safari ignore effectivement le paramètre charset de l’en-tête HTTP (premier bug) et utilise donc le jeu de caractère ISO-8859-1, mais fait une autre boulette en résolvant les appels de caractères (ici, \00A0) avant de convertir la feuille de style dans le même encodage (ici, l’UTF-8) que celui de la page liant la feuille de style. Résultat, l’espace insécable se retrouve encodée deux fois de suite en UTF-8. Le test suivant semble confirmer mon hypothèse puisque j’obtiens alors ce qu’affiche Safari (sauf l’espace, apparamment supprimé par Safari) :

<?php
header('Content-Type: text/plain; charset=UTF-8');

echo utf8_encode("\xC2\xA0");// \xC2\xA0 est l’espace insécable encodée en UTF-8 Le résultat affiché est  suivi d’une espace
?>

Bon, mon raisonnement est débile. Si Safari utilisait ISO-8859-1 pour la feuille de style, le guillemet fermant s’afficherait aussi de façon foireuse. Donc forcément, Safari utilise bien l’UTF-8 pour la feuille de style

Les appels de caractères (\00A0 en tout cas) sont donc résolus et le caractère résultant encodé dans le charset de la feuille de style. Ça semble être plus logique comme explication.

L’enfer des règles-at

Pensant d’abord pouvoir régler son compte au bug d’encodage avec la règle-at @charset (c’était avant d’en arriver à l’hypothèse du paragraphe précédent), et malgré le bug d’Opera et de la règle-at @charset que j’allais devoir lui aussi tenter de contourner, je décide d’ajouter des @charset "UTF-8"; (Rappel pour ceux qui n’ont pas vu ; Opera Mac ne semble pas affecter par le bug de la règle @charset, seules les versions Windows et Linux le sont). Par exemple, là :


@charset "UTF-8";
@import url("/une_feuille");
@import url("/une_autre");

html { font-size: .9em; }

Cela ne fait ni chaud ni froid à Safari (le bug du contenu généré demeure). Comme prévu, Opera perd la boule et ignore toutes les règles-at qui suivent immédiatement (ici, les deux @import) ainsi que la règle CSS suivante (ici, html { font-size: .9em; }). Quant à Firefox, les tests que j’avais fait à une certaine époque m’avaient fait constater qu’il ne gérait pas lui non plus la règle @charset, cependant, il a le bon goût de tenir compte de ce que je lui dis dans les en-têtes HTTP, il n’était donc pas concerné par ces tests. Et pourtant, j’ai la surprise de constater qu’il zappe lui aussi purement et simplement les deux règles @import. Gasp…

Après pas mal d’essais infructueux, un éclair de lucidité me pousse à retourner lire la recommandation CSS, dont la traduction n’était d’ailleurs pas accessible à ce moment-là. Heureusement, j’en ai une copie complète sur mon disque dur ;¬). Bref, je suis tombé là-dessus :

Il ne peut y avoir qu'une règle @charset dans une feuille de style externe et elle doit survenir au tout début de celle-ci, aucun caractère ne devant précéder. Cette règle ne doit pas apparaître dans une feuille de style incorporée.

Ah, forcément, fallait le savoir. Je comprends mal les raisons de cette limitation. Cela veut dire que toutes les feuilles de styles importées ont l’obligation d’être dans le même jeu de caractère que la feuille de styles principale. Et puis il y a un autre problème du coup :

La règle @import permet aux utilisateurs l’importation de règles de style à partir d’une autre feuille de style. Les règles @import doivent précéder toutes autres règles dans la feuille de style.

Ah ouais… Comment que je fais moi ? Bon, heureusement, CSS 2.1 vient éclaircir les choses comme toujours :

CSS 2.1 user agents must ignore any @import rule that occurs inside a block or after any valid rule other than an @charset or an @import rule.

Bon, je passe sur les essais avec @namespace pour contourner le bug d’Opera (que de toute façon, c’est pas valide puisque @charset doit être en premier) et les heures à tester/modifier/retester sinon, ce billet risque d’être déraisonnablement long. Encore une fois, merci à J.J Solari pour ses tests du design sur les navigateurs Mac et les impressions d’écran fournies. Il va finir par devenir mon testeur mac attitré si ça continue ;¬)

Tiens, un bug de plus :

label { float: left; width: 15em; }/* La présence du width n’est pas significative */
label { float: none; }

La mise en flottant passe automatiquement la boîte en type bloc (comme si on mettait explicitement display: block; (jusque là, tout est normal). Avec la règle suivante, on enlève le caractère flottant de la boîte. La boîte reste de type bloc sur Firefox 1.0 (Deerpark n’est pas affecté par ce bug).

Vos réactions, opinions, insultes…

Rétroliens

Faire un rétrolien sur ce billet : [trackback]

Commentaires

1. De Vincent • Site

Je connaissais ce bug de Safari et la seule solution que j'ai trouvé est de revenir à l'ASCII, Safari ne voulant pas comprendre lorsqu'on lui spécifie l'encodage à utiliser.

On peut toujours spécifier les caractères que l'on souhaite avec la syntaxe \NNNN pour ajouter un caractère Unicode en spécifiant son code.

Mais c'est vrai que cette limitation de Safari est bien étrange tout de même pour un navigateur aussi avancé.

2. De Bobe

J’ai édité mon billet car en fait, mon raisonnement était idiot puisque le guillemet fermant, encodé en utf-8 évidemment, est quant à lui bien affiché. Donc manifestement, Safari comprend bien quand je lui indique via http que la feuille de style est en utf-8, à moins qu’il ne considère qu’elle a le même encodage que la page html la liant.

Mais alors pourquoi encode t-il à nouveau les appels de caractères en utf-8 après les avoir manifestement résolu vers ce même encodage ? Mystère.

3. De S.F. • Site

Un » encodé en utf-8 donne un û s'il est affiché en latin1. Peut-être que tu peux creuser de ce côté là, tout bêtement. (je n'ai pas testé, n'ayant pas de mac ni de testeur mac)

Sinon, tu as reporté tous les bugs que tu as trouvé ? ^^

4. De Bobe

«Un "»" encodé en utf-8 donne un "û" s'il est affiché en latin1»

Le hic, c’est que dans le cas présent, le guillemet fermant est correctement affiché, donc en fait, Safari considère bien la feuille de style comme encodée en utf-8.

«Sinon, tu as reporté tous les bugs que tu as trouvé ? ^^»

Les bugs que j’ai rencontré sur firefox ont déjà une entrée dans le bugzilla ou ont été corrigés dans Deerpark, ou bien c’était des erreurs de ma part :¬) (le @charset dans les feuilles importées qui foutait le bordel par exemple).

Pour Opera et Safari, je ne sais pas comment ça se passe pour rapporter un bug.

L’ajout de commentaires sur ce billet n’est pas/plus autorisé.