Les classes conditionnelles en HTML

Astuce par (Intégrateur du Dimanche, Strasbourg)
Créé le , mis à jour le (92036 lectures)
Tags : css, xhtml, hacks, conditionnel, explorer, IE6, ie7, irish

Les cancres du Web, Internet Explorer 6, 7 et parfois 8, nous mènent souvent la vie dure. Même quand on s’abaisse à leur niveau, il leur arrive de ne pas comprendre, ou d’y mettre de la mauvaise volonté.

La solution classique (comprendre: à l’ancienne) est d’utiliser des hacks CSS. Ces derniers sont déconseillés car peu fiables; en effet, on ne sait jamais à l’avance quels seront les navigateurs sur le marché dans deux ou cinq ans, et comment ils comprendront ou pas nos hacks CSS. Une deuxième solution, conseillée par Microsoft et Alsacréations (que du beau monde :)), est d’utiliser les commentaires conditionnels.

Nous allons voir dans cet article que l’utilisation habituelle des commentaires conditionnels a quelques inconvénients, et proposer une technique qui combine plusieurs avantages : les classes conditionnelles.

Le problème des commentaires conditionnels

Les commentaires conditionnels se présentent comme des instructions dotées d’une condition (if) et qui peuvent se placer à n’importe quel endroit du document (X)HTML.

<!--[if IE]>
	<link rel="stylesheet" href="styles-ie.css" media="screen">
<![endif]-->

Il s’agit d’un mécanisme propre à Internet Explorer Windows, né avec la version IE5, et qui permet d’inclure dans une page HTML, de manière valide, une portion de code qui ne sera lue et interprétée que par IE, ou par l’une ou l’autre de ses versions.

Pour information, Internet Explorer 10 ne reconnaît plus les commentaires conditionnels, il ne peut donc plus être ciblé de cette manière.

Dans notre quête de compatibilité maximale sur le navigateur de Microsoft, nous allons principalement nous servir de ce mécanisme pour faire un lien vers une feuille de styles corrective dédiée. Cette seconde feuille CSS, chargée à la suite du fichier de styles principal, aura pour but d’écraser et de rectifier au cas par cas les règles générales mal reconnues par IE, comme le montre l'illustration ci-dessous :

[![Texte alternatif:!:commentaires conditionnels]!]

Cependant, dans la pratique, une feuille de style corrective pour Internet Explorer ne suffira pas. Vous serez souvent amenés à produire une feuille CSS spécifique à IE6 et 7, ainsi qu'une autre pour IE8. Ou pire : une feuille différente pour chacune des trois versions !

Au final, vous jonglerez avec au minimum trois feuilles de styles CSS :

[![Texte alternatif:!:commentaires conditionnels 2]!]

Non seulement, nous avons à gérer plusieurs fichiers différents, mais nous ne pourrions toujours pas cibler les trois versions IE6 et IE7 et IE8 à la fois sans ajouter une nouvelle condition et feuille CSS supplémentaire.

En 2008, le développeur américain Paul Irish s’est penché sur le mécanisme des commentaires conditionnels et en a listé ces quelques désagréments :

  • Les navigateurs anciens tels que IE6, IE7 et IE8 doivent charger plusieurs fichiers CSS au lieu d’un. Ces requêtes HTTP supplémentaires, ont un impact sur la vitesse d’affichage des pages.
  • Certains correctifs CSS s’appliquent à toutes les versions des navigateurs (IE6, IE7, IE8). Il faudra les écrire une fois dans chaque fichier de correctifs.
  • A chaque modification opérée sur styles.css, il faudra vérifier dans chacune des feuilles de correctifs CSS s’il n’y a pas également des changements à répercuter. La maintenance et l’évolution des styles CSS deviennent difficiles.
  • L'emploi de commentaires conditionnels peut causer des problèmes pour les téléchargements parallèles.

L’argument des baisses de performances est non négligeable sur les versions IE6 et IE7, car il s’agit justement de navigateurs vieillots nécessitant des optimisations constantes et nombreuses en vue de ne pas handicaper leurs temps de calcul et d’affichage.

Une alternative ? Les classes conditionnelles

La solution proposée par Paul Irish a été initialement de créer un nom de classe spécifique à l’élément <body>, via un commentaire conditionnel et sans nécessiter d’appel vers une feuille de styles. Je préfère néanmoins l’appliquer directement à l’élément <html>, plus logique et plus souple à manipuler.

Voici une version optimisée de classe conditionnelle :

<!--[if lte IE 7]> <html class="ie67 ie678" lang="fr"> <![endif]-->
<!--[if IE 8]> <html class="ie8 ie678" lang="fr"> <![endif]-->
<!--[if gt IE 8]><!--> <html lang="fr"> <!--<![endif]-->

Vous pouvez voir cette classe conditionnelle en action sur le site www.goetter.fr/livres/css-avancees/

Le principe et les explications sont simples :

  • sur les versions inférieures ou égales à Internet Explorer 7, le corps du document s’écrira <html class="ie7 ie67 ie678" lang="fr"> ;
  • sur IE8, ce sera <html class="ie8 ie678" lang="fr"> ;
  • sur tous les autres navigateurs (IE9+ et le reste du monde), il s’agira simplement de <html lang="fr">.

Il devient alors aisé d’appliquer une règle spécifique à IE6 et IE7 :

#kiwi { /* Pour tout le monde */  
  display: inline-block;  
}
.ie67 #kiwi { /* Pour IE6 et IE7 */  
  display: inline;
  zoom: 1;
}

Et pour appliquer des styles à la fois sur IE6, IE7 et IE8 :

#kiwi { /* Pour tout le monde */  
  font-size: 1.2rem;  
}
.ie678 #kiwi { /* Pour IE6, IE7 et IE8 */  
  font-size: 20px; 
}

Bien que la syntaxe demeure un tantinet rebutante et qu'un ajout de codes HTML soit nécessaire, cette méthode commence à faire son chemin parmi les développeurs web aguerris (elle figure même dans le gabarit par défaut proposé par HTML5boilerplate) car ses avantages sont séduisants :

  • Contrairement à ce que l’on pourrait croire, elle est parfaitement valide W3C / HTML et reconnue par tous les navigateurs,
  • On cible en toute simplicité les versions d'Internet Explorer souhaitées avec .ie7, .ie8, .oldie par exemple,
  • Pas de multiplication des requêtes, et des fichiers externes à vérifier et maintenir.

Et vous, que pensez-vous de cette technique ? L'utilisez-vous déjà en production ?

Commentaires

Nico3333fr a dit le

Intéressant, je reconnais que sur certaines intégrations, sans commentaires conditionnels, je n'arrive pas à m'en sortir. Il faudrait que je teste plus activement cette méthode, ça tombe bien, j'ai un site à faire qui va nécessiter des trucs spécifiques IE ! :)

kraygoon a dit le

J'utilise la version optimisée de classe conditionnelle sur tous les sites que je réalise depuis début 2011. Cependant, depuis peu, j'utilise sur le CMS que j'utilise (CMSMS) des conditions Smarty pour n'afficher au final que la balise <html> correspondant au navigateur.

rik24d a dit le

C'est en effet une très bonne technique.

Une autre alternative est d'utiliser le fait que les règles non comprises sont ignorées. Pour l'exemple d'inline-block, ça donne :
#kiwi {
zoom: 1;
display: inline;
display: inline-block;
}
Ça ne marche pas dans tous les cas mais lorsque c'est possible, ça permet de ne pas avoir à répéter les sélecteurs.

Petit ajout aussi, lorsque l'on utilise les commentaires conditionnels, cela cause des problèmes pour les téléchargements parallèles. Stoyan Stefanov a tous les détails http://www.phpied.com/conditional-comments-bl... En gros, rajouter un commentaire conditionnel vide en haut de page permet d'éviter ce problème (voir la dernière partie "Update: empty conditionnal comment").

Raphael a dit le

@rik24d : merci pour ton ajout au sujet des perfs. Je vais l'ajouter d'ailleurs :)

DirtyF a dit le

Les commentaires conditionnels pourront toujours être utilisés mais pour les versions antérieures à IE10. Pour faire la distinction entre les navigateurs anciens et les plus récents, il faudra utiliser la détection de fonctionnalité.
(source : http://blogs.msdn.com/b/ie/archive/2011/07/06...

Modernizr a donc encore de beaux jours devant lui.

tetue a dit le

J'ai toujours détesté les feuilles de style alternatives : en éparpillant ainsi le code, on complique la maintenance en favorisant les oublis... C'est la raison principale pour laquelle, en plus de la perfo, j'ai aussitôt adopté les sélecteurs conditionnels sur le tag html : http://romy.tetue.net/selecteurs-conditionnel... :)

Seb33300 a dit le

J'arrive pas à tout comprendre la.

Dans la 1ère partie de l'article vous dites que les commentaires conditionnels apportent des inconvénients et qu'il ne seront plus reconnu par IE10.

Et la solution donnée est à base de commentaires conditionnels. Donc si je comprend bien, ça ne fonctionnera pas avec IE10 ?

Raphael a dit le

@Seb33300 : les commentaires conditionnels posent des soucis à partir du moment où ils servent à appeler une ou des feuilles de styles externes.
Les classes conditionnelles, basées effectivement sur les commentaires conditionnels, ne font pas appel à des fichiers externes. Tous les styles demeurent dans le feuille de style unique globale.

Pour ce qui est de IE10, il ne reconnaît plus les commentaires conditionnels, ce qui est un détail et ne change rien puisque l'objectif est de cibler les anciens navigateurs, ceux qui présentent des faiblesses et des bugs.

jpvincent a dit le

J'allais réagir à propos du problème sur la performance du à ce bug sur IE, mais @rik24d l'a déjà fait et il "suffit" de laisser un commentaire conditionnel vide tout en haut.

petite réflexion :
- ce qu'on cherche à faire là, c'est à éviter les feuilles de style spécifiques aux navigateurs, ce qui pose des problème de maintenance et de perf. Ca c'est bien
- tout ça pour éviter les hacks dans la feuille de style. ça ça me semble moins bien :)

Les deux hacks que j'utilise tout le temps pour cibler soit IE6 tout seul ( _width par exemple) soit IE6 et IE7 ( *width par exemple ) ont le mérite d'être super simples à retenir et d'être là depuis longtemps.
Le fait qu'ils soient là depuis longtemps et utilisé par beaucoup de gens fait qu'il est très très peu probable qu'un navigateur dans les 10 années à venir se mettent à les interpréter du jour au lendemain. C'est un standard de fait, et le premier navigateur qui se met à l'interpréter va casser une majorité de sites donc c'est pratiquement sur que ça ne passera jamais.

A côté de ça, les classes conditionnelles me semble plus dangereux : si tu oublies le fix du commentaire conditionnel vide en début de source, les IE prennent une demie seconde d'affichage dans la vue. Vu comment la maintenance peut parfois être faite chez certains de mes clients, je ne m'y risquerais pas chez tous :)

Artemus24 a dit le

Bonjour à toutes et à tous,
je n'ai jamais entendu parlé des "classes conditionnelles" dans la littérature web que je possède. Est-ce récent comme innovation ? A l'inverse, les "commentaires conditionnels", je connais.
N'est-ce pas une grosse verrue que l'on veut nous faire avaler pour palier à des inconvénients de compatibilités ?
@+

Raphael a dit le

@Artemus24 : ce n'est pas récent. Comme je l'ai écrit, l'idée a émergé en 2008.
Pour ce qui est des lectures web... Comment dire... Il y a pourtant des livres qui en parlent (le mien par exemple ;))

Raphael a dit le

@Artemus24 : pour la grosse verrue, je n'ai pas compris. Tu as une autre méthode pour pallier aux incompatibilités des mauvais navigateurs ?

Patidou a dit le

Selon h5bp le problème de performance ne produit pas quand on utilise les classes sur l'élément html.

http://html5boilerplate.com/docs/The-markup/

Mais comme dit plus haut c'est valide uniquement en html5, au fana du validateur de décider. ;-)

Geoffrey C. a dit le

Hello,

J'ai juste un souci avec le titre de l'article, puisque les conditions sont posées en HTML et non en CSS. "Les classes conditionnelles en HTML", ou "les commentaires conditionnels en HTML" seraient plus corrects, non ?

Après je comprends bien que le but est d'utiliser ces classes dans la CSS, mais pour moi le titre est inexacte.

Intéressante cette solution pour les problèmes de perfs.

Bonne soirée ;)

Raphael a dit le

@Patidou , @Geoffrey C. : bien vu tous les deux, je fais des modifs en conséquence.

Felipe a dit le

@Raphael : je pense que l'interrogation d'Artemus24 vient du fait que "classe conditionnelle" est une contraction du concept de "classe créée via commentaire conditionnel" (et qui donc ne peut être ciblée que sur les navigateurs ayant compris le commentaire conditionnel, i.e. IE version dinosaure de la première décennie du XXIe siècle ^^). Mieux vaut exprimer les concepts nouveaux avec plus de 2 mots, surtout quand ils ressemblent à un ancien concept.

fuse a dit le

Je suis d'accord concernant l'aspect maintenance, largement facilité mais beaucoup moins sur l'aspect performance. Est ce qu'on peut considérer que c'est mieux de pénaliser un peu tous les navigateurs (en chargeant une feuille de style plus lourde), que de pénaliser plus lourdement les navigateurs boiteux ?

tetue a dit le

@fuse : Vaut-il mieux charger UNE feuille unique, certes un chouïa plus longue, ou une feuille principale ET son alternative print ET sa rustine pour IE, etc. ? D'expérience, il n'y a guère qu'une à deux dizaines de lignes dans les feuilles dédiées à IE : rien qui puisse causer de l'obésité. Alors pas d'hésitation : mieux vaut une feuille unique, joliment concaténée et minifiée :)

glow a dit le

Pour moi le seul "réel" avantage de la solution proposée est la maintenance simplifiée.
L'inconvénient : on a une balise html pas belle :p

un petit rappel : attention à ne pas se reposer trop rapidement sur les commentaires conditionnels. un code css astucieux et de l'amélioration progressive suffisent dans la majorité des cas.

gaten a dit le

En ciblant trop précisément les navigateurs, on rends également la maintenance plus difficile dans le temps.
Mais parfois, c'est indispensable.

Pour moi il n'y a que trois choses qui comptent : Les performances, la maintenabilité et la lisibilité du code.
A l'inverse, l'esthétisme du code n'a aucune importance. Les remarques du type "ma balise html n'est pas belle" me dépassent.

Donc l'astuce proposée me convient à 100%.

capse a dit le

Personnellement j'utilise pas les commentaires conditionnels mais je repère le navigateur en php, et selon, j'appel mes feuilles de style. J'ai rarement vue cette solution mais moi je trouve qu'elle fonctionne parfaitement bien !

Artemus24 a dit le

Bonsoir à toutes et à tous,
@ Raphaël : NON, il n'y a pas d'autres solutions. Et c'est pourquoi j'appelle cela une grosse verrue. La solution serait la convergence, pour tous les navigateurs, vers la même interprétation du code HTML et CSS. Mais là, c'est une autre histoire.
@+

Artemus24 a dit le

@ Capse : bien sûr qu'elle fonctionne parfaitement. Mais le problème est de trouver un juste milieu entre un code HTML et CSS optimisé pour tel ou tel navigateur, et la complexification qui en résulte en PHP pour obtenir ce résultat. Je ne sais pas si cette solution peut se justifier dans la maintenance. Une bonne verrue est parfois bien plus simple à gérer.

-o-pera a dit le

Tout comme bon nombre d'entre vous, je vise plutôt les performances.
Cependant, cette philosophie d'avoir du code intrusif dans la même feuille de style ne me réjouit pas vraiment.

Je ne suis pas vraiment fan non plus des classes conditionnelles dans le sens ou pour la maintenance, si on devait par exemple supprimer le support de IE6 on devrait supprimer une à une toutes les lignes au lieu de supprimer un seul et simple LINK.

De plus, pour la majeur partie des cas une feuille de style commune iE6/7 et largement suffisante pour palier à l'ensemble des bugs de ces navigateurs.

Et si on est très pointilleux, je doute que le zoom:1 soit valide W3C, tout comme les hacks dans une feuille de style (ceci dit ça ne veut plus rien dire avec tous les prefix que l'on a maintenant).

Ajoutons à ça le fait que le fichier de style de base sera beaucoup plus lourd pour l'ensemble des browsers si on utilise les classes conditionnelles.

A voir aussi, mais, je pense que le fait d'avoir des hacks ou des classes conditionnelles a une impacte sur le rendering (si quelqu'un a des benchs je suis preneur).

Car oui, il faut réduire le nombre de requêtes http au maximum, mais le rendering a aussi une place importante dans les perfs d'un site web.

Si l'objectif des perfs se base sur du long terme, c'est à dire cibler les navigateurs modernes, et que l'on souhaite avoir ce qu'il y a de plus propre et de plus maintenable, il est préférable peut-être de sanctionner IE avec une requête de plus.

Suivant les objectifs de chacun, les choix seront donc différents.

Pour conclure :

Avantages des classes conditionnelles
.Une seule requête HTTP, et centralisation de tous les styles
.Pas de hack IE pas propre * _ (quoique)

Inconvénients
.Maintenance difficile si on souhaite enlever le support d'un IE
.Vient se greffer à du code standard
.Perf du rendering
.Poids du fichier de style commun qui devrait être plus léger pour les autres browsers

fabien_ a dit le

Quand les modifications sont légères, je vous suggère de regarder ce qui se passe quand on tape "-height" ou "/height" au lieu de "height". La surprise pourrait être agréable.

duBy a dit le

@ -o-pera ;
Et pourquoi tu voudrais "supprimer le support de IE6"
Pour ça il faudrait d'abord supprimer IE6 lui-même =) !