Aller au contenu

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.

Articles (peut-être) similaires :
Internet Explorer 6 : ID, class et background, de Pierre Bertet (25 janvier 2008)
Webkit supporte document.querySelectorAll();, de Pierre Bertet (10 février 2008)

{ 24 } Comments

  1. Country | 9 avril 2008 at 14:20 | Permalink

    Merci pour l’astuce, c’est vrai que ça peut être un bon moyen pour réduire le nombre de fichier et donc les requêtes HTTP sur le serveur. Tout en évitant d’utiliser des hacks.

  2. Vincent Voyer | 9 avril 2008 at 14:43 | Permalink

    Par contre ça alourdit inutilement les css des autres navigateurs pour rien. Et eux ils ont rien demandé ! :)

  3. Eric Le Bihan | 13 avril 2008 at 13:22 | Permalink

    > Vincent
    On ne parle pas ici de faire une CSS par navigateur, mais de rationaliser l’organisation des CSS. Nous sommes d’accord qu’il vaut mieux éviter d’utiliser les hacks ou commentaires conditionnels quand c’est possible. Quand tu travailles avec une cinquantaine de développeurs et intégrateurs, je peux t’assurer que cette méthode est la plus facile à maintenir.

  4. Vincent Voyer | 14 avril 2008 at 11:33 | Permalink

    > Eric
    Je ne comprends pas, le but de l’article est bien d’éviter d’avoir des feuilles de style genre ie6.css, ie7.css ?

    Je notais simplement qu’avec cette méthode, sur un site relativement important tous les navigateurs se taperont la lecture (sans l’interprétation) des css des autres navigateurs. On obtient une perte évidente de bande passante, de performance. Par contre oui c’est surement plus pratique car on peut facilement identifié les correctifs spécifiques placés juste en dessous des règles standards.

    Il faut éviter les hacks mais les commentaires conditionnels sont pratiquement inévitables, on est d’accord.

    Je préfère vraiment utiliser des feuilles spécifiques pour ie6 et ie7.
    Surtout qu’avec un bon reset css (type yahoo) et un doctype qui évite le mode quirks, le nombre de règles pour IE7 reste léger et celles pour IE6 corrigent principalement des pngs alpha.

    C’est principalement basé sur mes expériences personnelles et je n’ai jamais travaillé avec 50 développeurs et intégrateurs alors j’ai le temps de changer d’avis.

    Notons tout de même que Facebook ou Digg pour ne citer qu’eux, utilisent les feuilles de style spécifiques à ie6 et ie7

  5. Eric Le Bihan | 14 avril 2008 at 12:15 | Permalink

    > Vincent
    Les billets que nous publions sur notre blog, visent à faire partager notre expérience et ne sont en aucun cas parole d’évangile. Nous proposons des solutions et des réflexions issues de notre expérience professionnelle. Libre à chacun de ne pas être en accord avec nos choix. Nous espérons juste offrir une solution alternative que certaines personnes trouveront comme nous, adaptée à leur contexte de travail.

  6. Pierre Bertet | 14 avril 2008 at 12:21 | Permalink

    > Vincent
    Voici une partie du commentaire laissé sur l’article de Britoweb, dans le but de mieux préciser le contexte, et surtout d’adoucir le débat ;)

    Je n’ai peut-être pas été assez clair quant à l’utilisation de cette technique : il ne s’agit pas de la solution parfaite, elle n’existe pas.

    L’utilisation d’une CSS séparée (qui est également évoquée dans l’article) n’est aucunement remise en cause : elle est au contraire tout à fait indiquée dans certains cas.

    Je pense que cette solution atteint ses limites dans le cadre de la maintenance d’un site relativement tentaculaire, maintenu par une équipe. La “CSS Internet Explorer” est finalement très peu utilisée, principalement pour deux raisons :

    Si les CSS sont découpées en plusieurs fichiers (pour une refonte progressive du site par exemple), il peut être risqué de voir un de ses sélecteurs s’appliquer sur une page pour laquelle il n’est pas destiné.
    L’utilisation d’attributs “id” pour cibler les pages réduit le risque, mais ne l’élimine pas : une propriété appliquée sur une partie du site peut en toucher une autre, car un attribut “id” existant sur une page peut être dupliqué par mégarde sur une autre.

    Ensuite, lorsque plusieurs personnes travaillent régulièrement sur les mêmes fichiers, il peut être difficile de comprendre que le bug qu’on essaye de résoudre depuis un moment est causé par une propriété définie par quelqu’un d’autre dans le “fichier Internet Explorer”.

    Dans ce cadre, c’est cette solution, bien qu’inélégante, qui me paraît la plus sécurisée, tout en conservant une relative qualité : le code HTML reste conforme à la recommandation HTML.

    Vous dites : « En outre, ça alourdit le code HTML. »
    Le HTML est autant alourdi qu’avec la définition d’une CSS additionnelle.
    N’oublions pas non plus que la structure HTML d’un site se voulant “compatible IE6″ est déjà largement plombée : les classes “first”, “last”, “odd” et “even” sont par exemple couramment utilisées pour pallier à l’absence de sélecteurs CSS 2.1, et la simple absence du sélecteur de classes multiples pénalise énormément l’architecture HTML/CSS.

  7. Vincent Voyer | 14 avril 2008 at 13:27 | Permalink

    Pas de soucis, l’essentiel c’est de discuter ! Merci pour les précisions.

  8. pinch | 25 avril 2008 at 15:35 | Permalink

    Et pourquoi ne pas appliquer l’id directement sur le body ?

  9. Julien Royer | 24 juillet 2008 at 16:14 | Permalink

    Intéressant, mais attention aux effets de bord indésirables sur la manipulation de l’arbre du DOM.

  10. Pierre Bertet | 24 juillet 2008 at 20:09 | Permalink

    Julien Royer :
    Il s’agit simplement de commentaires, il est rare (et risqué) de se baser dessus pour parcourir le DOM. Il s’agit bien de ce à quoi tu penses ?

  11. Wib | 13 août 2008 at 20:17 | Permalink

    C’est très agaçant de perdre son temps à adapter son code pour un navigateur qui n’est résolument pas pensé pour le web. Une raison de plus pour se passer des produits microsoft.

  12. .Nasty | 29 août 2008 at 17:02 | Permalink

    Je trouve ça bizarre un ID qui réunit les versions antérieurs à IE6 et celles pas encore sortis. C’est vrai qu’IE a la fâcheuse habitude de perpétuer ses bugs d’une version à l’autre, mais de là à imaginer qu’un bug va se retrouver sur IE5.5 et IE8 sans passer par la 6 ou la 7, c’est vraiment alambiqué.

    A la limite, je verrais plus un ID

  13. .Nasty | 29 août 2008 at 17:03 | Permalink

    A la limite, je verrais plus un ID

  14. .Nasty | 29 août 2008 at 17:05 | Permalink

    (désolé pour le tripple poste, j’ai d’abord cru à un nombre limité de caractères, mais je réalise que c’est le commentaire conditionnel qui coupe la fin de mon message, j’ai enlevé le ! pour la peine)

    A la limite, je verrais plus un ID pour les versions inférieures (quoique je doute qu’il y ait encore beaucoup d’intégrateurs qui se soucient de la compatibilité d’IE5.5), et un autre ID pour préparer les bugs des futures versions (mais en règle générale, on ne livre pas à un client un site compatible pour un navigateur qui n’est pas encore sorti :p).

  15. Pierre Bertet | 29 août 2008 at 20:46 | Permalink

    .Nasty : En fait, le but n’est pas vraiment de l’utiliser : je suis d’accord avec vous, il serait étrange de cibler à la fois IE5.5 et IE8 dans un même sélecteur.
    Il s’agit en fait d’ouvrir cet élément div sur tous les autres IE, puisqu’il est systématiquement fermé à la fin (</div> juste avant </body>).

    Le principe est exposé, mais libre à chacun de l’adapter comme il le souhaite : il serait envisageable d’utiliser à nouveau les commentaires conditionnels en bas de page, pour ne pas fermer ni ouvrir cet élément sur les “autres IE” (que 6 et 7).

    Une petite astuce utilisée dernièrement : placer une classe comme “IE6-7″ sur les deux premiers commentaires conditionnels, ce qui permet de cibler d’un coup IE6 et IE7, sans répéter deux fois le sélecteur.

    Pour Internet Explorer 8, tout ceci sera inutile, car il sera parfait ;-)

    Plus sérieusement, j’espère que ce navigateur permettra enfin à Microsoft et à ses clients d’entrer dans le web moderne. On pourra alors oublier en quoi consistait le métier d’intégrateur web lorsque IE6 et 7 étaient en circulation…

  16. .Nasty | 2 septembre 2008 at 13:27 | Permalink

    ok au temps pour moi, je n’avais pas pensé sur le coup pour la div fermante. Bien vu alors :)

  17. Théo | 23 septembre 2008 at 12:21 | Permalink

    De la balle cette astuce !
    merci beaucoup

  18. Julien Royer | 14 octobre 2008 at 9:23 | Permalink

    @Pierre : il ne s’agit pas que de commentaires, puisque l’on ajoute une div sous IE. On a donc un arbre différent sous IE par rapport aux autres navigateurs. Ceci dit, je suis d’accord avec le fait que des sélecteurs CSS/JS bien conçus ne devraient pas être affectés par cette différence.

  19. Pierre Bertet | 14 octobre 2008 at 11:00 | Permalink

    Julien :
    Nous avons le même arbre sur IE et sur les autres navigateurs, seul l’ID change. L’élément #NOTIE n’apparaît pas sous IE.
    J’ai l’impression de me répéter moi :-) (voir mon commentaire plus haut)

  20. Julien Royer | 14 octobre 2008 at 11:19 | Permalink

    @Pierre : oui, désolé.

  21. Jul | 14 novembre 2008 at 16:59 | Permalink

    Au lieu de rajouter un div, on peut très bien ajouter la classe IE6 à l’élément body.

  22. Pierre Bertet | 14 novembre 2008 at 17:01 | Permalink

    Jul : Je t’invite à lire les commentaires au-dessus du tien ;)

  23. Enisséo | 14 décembre 2008 at 19:19 | Permalink

    Je ne sais pas si ça a déjà été mentionné dans les commentaires, mais j’utilise personnellement le hack multiclass pour ie6 :
    .maClasse {
    propriétés tous navigateurs
    }
    .ie6.maClasse {
    propriétés IE6
    }

    Aussi propre (voire +) que le #IE6 .maClasse, ne nécessite pas de commentaires conditionnels, mais pourrait fonctionner avec (en faisant un body class=”ie7″ en commentaire conditionnel, par exemple).
    Par contre, il nécessite que le style s’applique à un élément avec une classe CSS, ou ayant un parent avec une classe CSS.

  24. Bertrand | 11 février 2009 at 13:36 | Permalink

    Avant de tenter des hacks ou différentes formes d’aiguillages tels que des CSS supplémentaires, nécéssaires mais souvent louds à gérer, il est important d’avoir bien fait le tour de votre feuille de style.
    je parcourais ce post à la recherche de la solution miracle, ayant moi-même des problèmes de décalages sur Opéra et FF … IE7 fonctionne étonamment bien.
    Or il y a un outil hyper puissant sur Opéra qui s’appelle l’ Outil de développeur (voir Outils / Avancé / Outils de développeur).
    J’ai analysé le code à l’aide de cet outil et je me suis rendu compte que les décalages provenaient d’une balise ul… le problème est aujourd’hui identifié, réglé, tout cela sans alourdir la feuille de style ou créer d’autres fichiers !
    Et pour conclure, un grand Merci à l’ auteur de ce post

{ 3 } Trackbacks

  1. Blog - Britoweb | 11 avril 2008 at 21:42 | Permalink

    Les CSS et les commentaires conditionnels, ou l’art d’user de ces derniers avec une certaine modération…

    Le site Les intégristes a récemment publié un billet intitulé Cibler Internet Explorer dans une CSS ? Oui, et sans hack….

  2. [...] site est d’abord conçu pour les standards, puis adapté pour Internet Explorer, de manière plus ou moins élégante. Les exigences pour ce vieux navigateur ont été globalement revues à la [...]

  3. [...] savoir plus chez lesintegristes.net [...]

Publier un commentaire

Votre email ne sera jamais publié ou transmis à un tiers. Les champs requis sont marqués : *