Plan de site Navigation
Blog & Blues Techniques et Standards de la Qualité Web

Accueil > weblog


- Lire le billet précédent - Lire le billet suivant -

Feuilles de style, jeux et codage de caractères

Par Laurent Denis, le 19 février 2005.

Si le problème des jeux et du codage des caractères dans les documents HTML est fréquement traité, cette question est revanche plus rarement abordée quand il s'agit de feuilles de styles. Les documents CSS sont pourtant eux aussi susceptibles de contenir des caractères absents de leur encodage (character encoding), en particulier lorsqu'il s'agit de contenu généré CSS. Le rendu de ces caractères peut alors être problématique.

Dans quels cas pouvons-nous avoir besoin de tels caractères ? Quelles sont alors les contraintes dont il faut tenir compte, et les précautions à prendre ?

Dans quels cas l'encodage peut-il être problématique en CSS ?

Selon la spécification CSS2 :

Une feuille de style CSS est une séquence de caractères issus du Jeu de Caractères Universel, Universal Character Set (voir [ISO10646]). Pour leur transport et leur stockage, ces caractères doivent être encodés selon un codage compatible avec le jeu de caractères disponibles en US-ASCII (ex. ISO 8859-x, SHIFT JIS, etc.).

Le vocabulaire CSS lui-même (sélecteurs, propriétés, valeurs usuelles de celles-ci, etc.) ne faisant appel qu'aux caractères US-ASCII, il ne pose donc aucun problème apparent : une information d'encodage erronée ou absente n'entraînera pas d'erreur perceptible lors de l'affichage du document auquel s'applique la feuille de style.

Mais il peut en être tout autrement, pour peu qu'une chaîne quelconque présente dans la feuille de syle contienne des caractères non US-ASCII. Cela peut se produire en particulier lorsqu'on souhaite :

  • Gérer les types de guillemets (valeur de la propriété quote) : les guillemets français « et » sont absents du jeu de caractères ASCII.
  • Générer un pseudo-contenu (valeur de la propriété content), tel qu'un mot contenant des caractères accentués, ou le tiret cadratin — précédant les paragraphes de dialogue, etc. ;
  • Utiliser un sélecteur d'attribut HTML ([foo=...]) : img[alt~="été"], par exemple, viserait, dans une galerie d'images, toutes les images dont l'attribut alt contient le mot été ;

Plus théoriquement, le problème pourrait se poser également :

  • Pour un nom de police de caractère (valeur de la propriété font-family ;
  • Pour le nom d'un attribut ou d'un élément (ne concerne pas HTML4.01 ni XHTML1.x).

Nous prendrons ici l'exemple des guillemets généré pour l'élément q (citations en ligne), qui correspond sans doute au cas le plus fréquent. Comment allons-nous gérer ces caractères ?

Encodage et styles internes

Le contenu de l'attribut style des éléments HTML est interprété selon l'encodage du document lui-même, comme tout autre contenu. Autrement-dit :

  • Si le caractère visé appartient à l'encodage du document, il est possible de l'écrire directement. C'est le cas des guillemets français « et » en ISO8859-1, ISO8859-15 et UTF-8.
  • Dans le cas contraire, il est possible de recourir aux entités numériques, qui adressent directement le caractère dans le jeu Unicode, ou aux entités caractères, qui font de même par l'intermédiaire des alias définis dans les DTD HTML et XHTML. Autrement-dit, les guillemets français pourront être obtenus à l'aide de :
    • « : « ou «
    • » : » ou »
  • Mais il est également possible de recourir à un mécanisme propre au contenu CSS, qui permet d'atteindre ces caractères à l'aide du caractère d'échappement \ suivi du nombre hexadécimal référant le caractère en Unicode. Nous obtiendrons alors nos guillemets à l'aide de :
    • « : \00AB (le 171 précédent s'écrit AB en numération hexadécimal)
    • » : \00BB (le 187 précédent s'écrit BB en numération hexadécimal)

Il semble donc que nous ayons, pour les styles en ligne, un vaste choix. Mais la prudence incite à restreindre celui-ci, en évitant entités numériques et entités caractères. En effet, si nous abordons maintenant le cas des styles internes contenu dans l'élément style, nos possibilités se réduisent :

  • Il est toujours possible d'écrire directement nos guillemets sous la forme « et », si ces caractères existent dans l'encodage choisi pour notre document HTML (ISO8859-1, ISO8859-15 et UTF-8).
  • Il est toujours possible d'utiliser les séquences échappées \00AB et \00BB, puisqu'il s'agit toujours d'un contenu CSS.
  • Mais nous ne pouvons plus utiliser les entités numériques « et », ni les entités caractères « et » car celles-ci ne sont pas interprétées dans le contenu des éléments style et script.

Afin d'éviter toute erreur, et notamment dans le cas où un style en ligne serait transféré dans une feuille de style interne, il convient donc de s'en tenir, pour tout style présent dans un document HTML, aux seuls caractères directement saisis lorsque cela est possible, ou aux séquences échappées hexadécimales dans le cas contraire.

On écrira donc :

<style type="text/css">
<!-- 
q {
quotes: "« " " »";
}
 -->
</style>

ou:

<style type="text/css">
<!-- 
q {
quotes: "\00AB " " \00BB";
}
 -->
</style>

ou:

<q style="quotes: '« ' ' »'">Lorem ipsum...</q>

ou enfin:

<q style="quotes: '\00AB ' ' \00BB'">Lorem ipsum...</q>

Bien qu'ils soient tout à fait valides, on évitera donc en revanche :

<q style="quotes: '&#171; ' ' &#187;'">Lorem ipsum...</q>

<q style="quotes: '&laquo; ' ' &raquo;'">Lorem ipsum...</q>

Encodage et styles externes

Lorsqu'il s'agit d'une feuille de style externe, nous retrouvons ces deux possibilités : échappement ou écriture directe. Entités numériques et entités caractères sont à nouveau exclues. Mais cette fois, ce n'est plus l'encodage du document HTML que nous devons prendre en compte, mais celui de la feuille de style elle-même.

En effet, comme tout document texte, une feuille de style est caractérisée par un encodage. Celui-ci peut être déterminé :

  • A partir de la valeur de charset spécifiée par l'entête HTTP Content-Type: text/css; charset="...". Dans une feuille de style du type style.php, celui-ci peut être obtenu à l'aide de l'instruction PHP  :
    <?php header('Content-Type: text/css; charset=ISO-8859-1;') ?>
    Il peut également être fixé pour toutes le feuilles de styles d'un répertoire (et des répertoires descendants) à l'aide du fichier .htaccess :
    AddType 'text/css; charset=ISO-8859-1' css

    Cette instruction aura priorité sur l'encodage par défaut déterminé par la configuration du serveur Apache, si celle-ci ne vous convient pas.

  • A défaut d'entête HTTP, à partir de la valeur de la pseudo-règle @charset placée en tout début de la feuille de style. L'information d'encodage est alors conservée lorsque le document est enregistrée localement ;
  • A défaut des mécanismes précédents, à partir de la valeur d'un éventuel attribut charset de l'élément link ou de l'instruction <?xml-stylesheet?> liant la feuille de style ;

Par conséquent, on pourra écrire :

En XHTML :

<?xml-stylesheet
   type="text/css"
   href="foo.css"
   charset="iso-8859-1" ?>

ou :

<link
   rel="stylesheet"
   href="foo.css"
   type="text/css"
   charset="iso-8859-1" />

Et en CSS :

@charset "ISO-8859-1";
q {
quotes: "« " " »";
}

Ou, lorsque l'encodage n'est pas précisé par l'un des mécanismes ci-dessus :

q {
quotes: "\00AB " " \00BB";
}

Echappement ou saisie directe, comment choisir ?

La saisie directe des caractères n'est possible que si ceux-ci appartiennent à l'encodage choisi, et exige que cet encodage (charset) soit correctement défini au moins au niveau serveur, et de préférence reproduit par une règle @charset. Elle présente en revanche l'avantage rendre le document CSS nettement plus lisible.

Le recours aux séquences échappées CSS peut cependant être jugé préférable, lorsqu'il ne s'agit que d'un petit nombre de caractères. Il permet par ailleurs d'obtenir un document CSS beaucoup moins ambigu lorsque ces caractères sont des espaces, tels que, par exemple :

  • \00A0, l'espace insécable connue par ailleurs sous la forme &nbsp; ou &#160;
  • \2009, l'espace fine insécable connue par ailleurs sous la forme &thinsp; ou &#8201; (non reconnue par IE et représentée sous forme d'une espace plus large que la normale par les navigateurs Gecko).

Pour éviter d'éventuelles confusions, on préfèrera donc souvent utiliser la forme échappée :

q {
quotes: "\00AB\00A0" "\00A0\00BB";
}

ou

q {
quotes: "\00AB\2009" "\2009\00BB";
}

(Ce qui permettra à nos guillemets français ci-dessus de mieux respecter l'usage typographique smiley clin d'oeil )

Trackbacks

Les trackbacks pour ce billet sont temporairement fermés en raison d'une série d'attaques de spam.

Commentaires

glandium, le 19 février 2005

encodage est un anglicisme. En français, on dit codage.

Moz, le 19 février 2005

Et si aucun encodage n'est indiqué, est-ce que le navigateur rattrape l'erreur, comme pour HTML ? Il applique l'encodage par défaut indiqué dans les préférences ?

Bobe, le 20 février 2005

À priori, il part dans ce cas du principe que l'encodage est le même que celui du document.

Philippe, le 20 février 2005

Il est également important de coder les feuilles de style si la dite feuille contient des commentaires /* bla */ en une autre langue, par example en Japonais, Chinois, ... A la limite, cela peut induire le navigateur en erreur, et ne pas lire la fin de commentaire (*/)

Note que je doute fort que IE Windows comprenne le @charset. L'entête HTTP fonctione correctement pour tous les navigateurs.

Laurent Denis, le 20 février 2005

Philippe: "Note que je doute fort que IE Windows comprenne le @charset."

Je ne vois pas ce qui permettrait de l'affirmer, ni de le vérifier : IE n'implémente ni les contenus générés (et donc pas la propriété quotes), ni les sélecteurs d'attributs. Les questions courantes de charset CSS lui sont donc en fait indifférentes.

Philippe, le 20 février 2005

.nom-de-selector-écrit-en-japonais {color:green}

<a href="dev.l-c-n.com/_temp/test_...

Philippe, le 20 février 2005

Excuses pour le lien.... smiley confus

dev.l-c-n.com/_temp/test_...

zaz, le 10 mars 2006

(«encoder» ; «encodage» est dans le Robert depuis 1960;) )

Les commentaires pour ce billet sont temporairement fermés en raison d'une série d'attaques de spam.