Cibler Internet Explorer dans une CSS ? Oui, et sans hack.
La méthode commence à être rodée : pour intégrer un design en CSS, on commence par le faire sur un navigateur “moderne”, puis on corrige les différents problèmes rencontrés sur Internet Explorer, surtout dans sa version 6, qui commence à sérieusement à s’incruster.
Pour cela, il existe plusieurs solutions.
Eviter les embrouilles
Avec la pratique, un certain nombre de réflexes se mettent en place, et on anticipe immédiatement les problèmes.
Un float:left, avec une marge sur sa gauche ? Un display:inline placé dans la même déclaration permet d’éviter le bug de la double marge. Tous les navigateurs ignorent ce display:inline, car la propriété float est prioritaire. C’est toujours ça de pris.
Malheureusement ça ne suffit pas toujours, et il n’y a parfois d’autre solution que de déclarer une propriété spécialement pour IE.
Le bon vieux hack
Allons-y joyeusement, il faut résoudre un bug sur IE6, et les hacks semblent pratiques et simples à utiliser.
Allez, au hasard… Le sélecteur d’enfant : html > body
IE6 ne comprend pas le sélecteur “>”. Il donc est possible de profiter de ce bug pour cibler IE6, de cette façon :
.my_element{margin-left:5px;} /* Cette déclaration est interprétée par tous les navigateurs */
html > body .my_element{margin-left:8px;} /* ... Puis est écrasée par la suivante, sauf pour IE6 qui ne comprendra pas cette déclaration. */
C’est pratique. Seulement IE7 ne corrige pas le bug pour lequel nous devions corriger la propriété margin. Pour le sélecteur d’enfants, pas de problème, IE7 l’interprète. Logiquement, le bug réapparaît.
En suivant la même méthode, il faut donc trouver un nouveau bug de sélecteur dans IE7, et revoir la CSS. Il arrive également que IE7 ne doive pas recevoir la même correction. Il faut donc trouver un bug qui s’applique à IE7 mais pas à IE6.
Et comment être sûr de ne cibler qu’IE6 ? Un autre navigateur ne prenant pas en charge ce sélecteur pourrait exister.
Il nous faut une autre solution, permettant de cibler efficacement Internet Explorer.
Les commentaires conditionnels
Microsoft a ajouté quelque chose de formidable à Internet Explorer : les commentaires conditionnels.
Ils permettent de ne servir un contenu qu’à Internet Explorer en général, ou à une de ses versions, en utilisant une syntaxe particulière à l’intérieur de commentaires HTML.
Ils n’ont certainement pas être prévus pour ça au départ, mais ils sont aujourd’hui principalement utilisés pour corriger les bugs de ce navigateur.
Il est donc possible d’utiliser le code suivant :
<!--[if IE 6]> <link rel="stylesheet" href="styles/internet-explorer-6.css" type="text/css" media="screen" /> <![endif]-->
Pour un navigateur suivant la spécification HTML4.01, la balise <link> est simplement ignorée car elle est placée dans un commentaire, mais pas pour Internet Explorer. Il va lire ce commentaire, et si une condition est déclarée, et qu’elle correspond au navigateur utilisé, le code sera tout de même interprété.
Cette solution est fiable, car il n’existe aucune raison pour qu’un autre navigateur interprète, dans le passé ou l’avenir, un commentaire de ce type.
Il est donc possible de créer une CSS pour IE6, une autre pour IE7 au cas où, et allez, encore une pour les versions d’IE inférieures à 8, histoire de cibler toutes les version passées de ce vieil ami.
Nous voici donc avec notre feuille de style, et une, deux voire trois nouvelles pour Internet Explorer. Si les CSS du site sont réparties sur plusieurs fichiers, il va falloir créer autant de nouveaux ensembles de fichiers “IE”, ou les utiliser de manière globale en prenant le risque d’appliquer à certaines pages des styles qui ne leur sont pas destinés.
Avec le temps, cette solution est beaucoup moins pratique : il faut jongler avec plusieurs fichiers, se souvenir que la déclaration de la ligne 310 du fichier “home.css” est corrigée à la ligne 14 du fichier “internet-explorer-6.css”, mais aussi à la ligne 8 du fichier “internet-explorer-7.css”.
Il se pourrait aussi qu’un jour cette correction provoque un effet indésirable, placée dans un certain contexte. Il faudrait alors se souvenir que cet élément a été corrigé dans l’autre CSS, et que cette correction peut être la cause du dysfonctionnement.
Mais existe-t-il une méthode fiable et pratique ? P’t'êt’ bien, ouais.
Les commentaires conditionnels, en plus malin
Il s’agit avec cette technique d’utiliser les commentaires conditionnels non pas pour appeler une feuille de style, mais pour entourer la page d’un conteneur qui prendra comme attribut “id” IE6, IE7, IE ou encore NOTIE.
Cet identifiant permettra de cibler précisément une version d’Internet Explorer, dans une CSS “normale”.
Le code se présente sous cette forme :
<body>
<!--[if IE 6]><div id="IE6"><![endif]-->
Et avant la balise de fermeture </body> :
<!--[if IE 6]></div><![endif]-->
</body>
Pour les navigateurs “normaux” et un outil de validation html, il s’agit de commentaires html tout à fait classiques, et sont ignorés.
De cette manière, il est aussi possible d’ajouter le support d’IE, en ajoutant une balise d’ouverture <div id="IE7"> en haut et en modifiant la condition du bas pour cibler IE6 et IE7 à la fois.
Nous pouvons aussi utiliser des conditions de type “n’est pas”, ce qui permet de cibler tous les navigateurs sauf IE.
Voici le code modifié :
<body>
<!--[if IE 6]><div id="IE6"><![endif]-->
<!--[if IE 7]><div id="IE7"><![endif]-->
<!--[if (IE) & (!IE 6) & (!IE 7)]><div id="IE"><![endif]--> <!-- Pour les anciennes et prochaines versions d'Internet Explorer (autres que 6 et 7) -->
<!--[if !IE]>--><div id="NOTIE"><!--<![endif]--> <!-- Le commentaire est fermé, puis rouvert -->
<!-- Structure HTML de la page -->
</div> <!-- Une simple fermeture de balise à la fin, car tous les navigateurs sont ciblés. -->
</body>
Il suffit ensuite d’utiliser ces sélecteurs de la même manière qu’un hack, mais plus clairement, plus facilement et surtout de manière fiable :
.mon_element{margin-left:2px;}
#IE .mon_element{margin-left:3px;}
#IE6 .mon_element{margin-left:4px;}
#IE7 .mon_element{margin-left:5px;}
#NOTIE .mon_element{margin-left:6px;}
Evidemment l’exemple est stupide, puisqu’il n’y a aucune raison de cibler tous ces éléments à la fois.
Les avantages sont nombreux :
- C’est fiable : une nouvelle version d’Internet Explorer sera considérée comme “standard” (mais attention à l’utilisation de #NOTIE, qui ne sera vraisemblablement pas reconnue par les futures version d’Internet Explorer)
- Une seule CSS à maintenir
- Le code HTML et CSS reste parfaitement valide
- La déclaration a du sens, il n’est pas utile de commenter ceci :
#IE6 .mon_element{margin:-3px;} - Lors de la sortie d’une nouvelle version d’IE, il suffit de lister les bugs qui n’ont pas été corrigés, et d’ajouter une nouvelle déclaration (IE8) pour ceux-ci.
A vous ensuite de composer avec ces différents exemples pour créer une structure adaptée à vos besoins : l’utilisation des éléments <div id="IE6"> et <div id="IE7"> devraient suffire à la majorité des cas.
