Sprites CSS : performance et maintenabilité

Openweb.eu.org > Articles  > Sprites CSS : performance et maintenabilité

Abstract

L’optimisation des performances des sites implique de diminuer le nombre de requêtes HTTP. Pour ce faire, il est possible de regrouper les images utilisées dans les CSS, cette technique s’appelle les sprites CSS.

Article

Présentation de la technique

La technique dites des sprites CSS consiste à exploiter un fichier unique pour stocker de multiples images, positionnées les unes à côté des autres. Celles-ci seront ensuite appelées dans la feuille de style, et la fenêtre d’affichage sur l’une ou l’autre image sera définie en CSS grâce à la propriété background-position.

Les avantages des sprites CSS sont multiples :

  • cela permet de se passer totalement de JavaScript : il n’y a pas besoin de préchargement d’images ni de gestionnaire d’événement comme onmouseover pour déclencher l’effet survolé, tout se fait via les propriétés CSS,
  • dans les cas de recherche de performances ou d’optimisations pointues, cette technique permet d’obtenir des résultats très intéressants en réduisant le nombre de requêtes au serveur pour afficher plusieurs images,
  • comme cette technique se base sur (X)HTML et CSS, tous les avantages de ces derniers utilisés à bon escient sont présents : séparation présentation/structure, code lisible et léger, accessibilité, etc.

Attention : la technique des sprites CSS n’est utile que pour des images à but décoratif, il ne faut pas remplacer toutes les images ainsi. Les images faisant partie du contenu doivent rester dans le code HTML.

Exemple d’intégration d’un menu de navigation

Plutôt qu’un long discours, voyons comment construire un menu de navigation utilisant cette technique. Voici le code HTML de ce menu :

<ul id="navigation" role="navigation">
  <li>
   <a href="#" id="aboutsprites" class="active"><span>A propos des sprites</span></a>
  </li>
  <li>
   <a href="#" id="spritesci"><span>Sprites par ci</span></a>
  </li>
  <li>
   <a href="#" id="spritescss"><span>Sprites via CSS</span></a>
  </li>
  <li>
   <a href="#" id="spritesinside"><span>Sprites inside</span></a>
  </li>
</ul>

Nous avons donc une image contenant les trois états possibles (de bas en haut) : actif (page courante), normal et survolé.

Image contenant les sprites

Il va de soi qu’il est possible d’utiliser les sprites CSS de plein de manières différentes. Le postulat de cet exemple est le suivant : l’image de fond de #navigation contiendra la partie de l’image avec les liens dits « actifs », et les liens seront positionnés chacun par dessus.

Principe du sprite de l'exemple

Quand on survolera le lien, il suffira de décaler l’image. Si un élément doit être affiché comme actif (pour indiquer à l’internaute sur quelle partie il se situe), il utilisera une classe active, qui fera disparaître l’image du lien... ce qui fera apparaître l’image de fond.

Les propriétés générales permettent de positionner l’arrière-plan et le menu, ainsi que le texte du lien :

#navigation{
  margin:0 auto;
  padding:0;
  width:549px;
  height:70px;
  background:#fff url(sprites.jpg) 0 -140px no-repeat;
}

/* pour chaque lien, propriétés communes */
#navigation li{
  float:left;
  list-style-type: none;
}
#navigation a{
  margin:0;
  display:block;
  height:70px;
  width:97px;
  background:url(sprites.jpg) 0 0 no-repeat;
  font-size:17px;
  padding:20px 22px 0 18px;
}

La liste navigation prend donc en fond la partie de l’image contenant les images des liens actifs. Chaque lien vient se positionner et aura la même image de fond, les textes sont également positionnés à l’aide du padding.

Ensuite, chaque fond de chaque lien est positionné.

#navigation #aboutsprites{
  background-position:0 -70px;
}
#navigation #spritesci{
  background-position:-137px -70px;
}
#navigation #spritescss{
  background-position:-274px -70px;
}
#navigation #spritesinside{
  background-position:-411px -70px;
}

L’effet de survol se fera en décalant l’image de fond, dans notre exemple, elle sera décalée de 70 px vers le haut pour chaque lien.

#navigation #aboutsprites:hover,
#navigation #aboutsprites:active,
#navigation #aboutsprites:focus{
  background-position:0 0;
}
#navigation #spritesci:hover,
#navigation #spritesci:active,
#navigation #spritesci:focus{
  background-position:-137px 0;
}
#navigation #spritescss:hover,
#navigation #spritescss:active,
#navigation #spritescss:focus{
  background-position:-274px 0;
}
#navigation #spritesinside:hover,
#navigation #spritesinside:active,
#navigation #spritesinside:focus{
  background-position:-411px 0;
}

Note : les propriétés background-position-y et background-position-x existent et auraient été bien utiles dans ce cas. Mais elles ne sont pas reconnues comme standards, et donc ne sont pas implémentées dans tous les navigateurs. Dommage !

Le menu est presque terminé, il ne nous reste plus qu’à désactiver le soulignement du texte des liens.

#navigation a{
  text-decoration:none;
}

La classe active est assurée simplement par cette ligne.

#navigation .active{
  background-image:none;
}

Voici le résultat final de l’exemple de menu utilisant les sprites CSS.

Attention : une précédente version utilisait une technique très légèrement différente, toutefois, un bug curieux sur certaines vieilles versions d’Internet Explorer empêche le fonctionnement optimal de ce menu (le clic droit sur le texte du lien pour l’ouvrir dans un nouvel onglet ne fonctionne pas correctement). À ce jour, nous n’avons pas d’explication rationnelle à vous donner... si ce n’est que le problème semble venir de display:inline-block sur le span du menu. En contournement, la nouvelle version utilise la propriété padding sur #navigation a pour positionner le texte à l’intérieur du lien.

L’exemple peut être qualifié de cas d’école et fonctionne très bien :

  • au lieu de 12 requêtes (3 états fois 4 images), nous avons une seule requête HTTP pour l’image de notre menu de navigation,
  • le code CSS est plutôt léger et relativement simple,
  • aucun code Javascript n’est nécessaire pour le faire fonctionner,
  • comme dans l’exemple, les images ont un lien logique entre elles (ce sont toutes les images du menu de navigation), générer cette image reste aisé, il n’y a pas de forte contrainte de positionnement pour le graphiste,
  • le décalage étant instantané, l’illusion d’image réactive est parfaite,
  • le code HTML reste très "naturel", ce qui implique une dégradation correcte si les CSS sont désactivées et une facilité d’évolution (version smartphone, refonte, etc.),
  • les sélecteurs permettant de définir le menu sont extrêmement simples et efficaces : la vitesse de rendu en sera améliorée,
  • comme le texte de chaque lien n’est pas pris dans l’image de fond, le texte du lien reste visible si les images sont désactivées ou injoignables,
  • petit détail qui a son importance : si les images sont effectivement désactivées ou injoignables, il faut penser à vérifier que la couleur de fond du lien soit bien identique à celle de l’image. Dans notre exemple, c’est assuré par background:#fff; dans #navigation.

Conclusion

Cette technique dite des sprites CSS permet de concilier une intégration CSS sans préchargement avec des contraintes de performances, dans notre cas, sans pour autant perdre en accessibilité.

Evidemment, mettre toutes les images en une seule peut compliquer la maintenance du site. Pour des raisons pratiques, il sera préférable de regrouper les images ayant un lien logique entre elles. Si la quête de performances doit être poussée à l’extrême pour un site à très fort trafic, toutes les images décoratives du site peuvent être groupées, dans ce cas, il sera nécessaire de définir exactement où doivent être positionnées chacune desdites images.

A titre d’exemple récent, les sprites CSS ont été utilisés pour le logo de Google commémorant l’anniversaire de Les Paul. Vous pouvez voir l’image utilisée pour réaliser le logo animé.

Références, compléments :

À propos de cet article

  • Openweb.eu.org
  • Profil : Expert, Gourou
  • Technologie : CSS
  • Thème : Mise en page, Qualité
  • Auteur :
  • Publié le :
  • Mise à jour : 18 février 2014
  • 13 commentaires

Vos commentaires

  • Le 6 décembre 2011 à 17:23

    Très bonne introduction aux sprites CSS. Pour la plupart de mes projets j’utilise ce générateur de sprites en Java qui a l’avantage de pouvoir être appelé au moment du déploiement en prod, via un script ant et des commentaires ajoutés dans le fichier CSS original. Du coup on l’installe et on l’oublie :)

    Nicolas Chevallier

  • Vivien Le 3 janvier 2012 à 16:56

    Bonjour, je trouve que cet article est une très bonne approche des sprites CSS. Je les utilise à titre professionnel souvent dans mes projets, surtout pour les boutons de barres de navigation et pour les icônes.
    Une astuce qui peut peut-être servir à d’autres, le fait d’espacer les illustrations dans un sprite d’un nombre de pixels systématiquement identique peut-être d’une grande utilité pour retrouver facilement la position d’un élément. Par exemple de petites icônes peuvent être placées tous les 30px sur une grille, retrouver la n éme icône est auquel cas très aisé.

    Vivien Blasquez

  • Guillaume Le 11 janvier 2012 à 13:29

    Bonjour, cet article présente bien les Sprites CSS qui peuvent vraiment se révéler très puissant à utiliser. Je m’en sers fréquemment pour la réalisation des menus de mes sites clients . Ca donne vraiment un effet très propre.

    Guillaume Debreu

  • aureg Le 5 mars 2012 à 16:08 En réponse à : Anonyme

    Excellent petit générateur, très pratique et assez intuitif à utiliser :-) Merci pour le lien

    Et merci à l’équipe OpenWeb pour cet article, encore une fois, très intéressant.

    Aurélien

  • Franck Le 4 septembre 2012 à 14:59

    Très bon tuto, seulement, après mettre relu 2 fois mon état actif ne fonctionne pas ! Et je m’arrache les cheveux pour trouver une solution, un peu d’aide serait la bienvenue. voici la page sur laquelle on trouve mon menu http://createchinfographie.fr/site-dedie/residence.php...merci

  • Nicolas Hoffmann Le 4 septembre 2012 à 17:23

    Franck : vous êtes sûr ? J’ai l’impression que ça marche. :)

  • Franck Le 4 septembre 2012 à 18:00

    Eh bien en fait le hover fonctionne très bien, seulement l’état actif reste sur "accueil" et ne change pas en fonction des pages sur lesquelles on est !

  • Nicolas Hoffmann Le 5 septembre 2012 à 08:43

    Normal, il faut que la classe active soit sur l’élément qui doit être actif, là, elle reste sur accueil.

  • Franck Le 5 septembre 2012 à 16:35

    L’interet de la chose etait de voir sur quelle page on se trouve en observant le menu. J’ai finalement solutionner la chose en plaçant un id sur la balise body de chaque page, puis dans les css j’ai indiqué à mes ID de décaler le background position selon l’image de sprite que je voulait afficher....le résultat est impecable !!

  • Marco Le 29 octobre 2012 à 12:19

    Bonjour,

    Merci pour cet article, qui présente un bonne base de réflexion sur les sprites.
    Je me pose toutefois une question sur les ouvertures présente en fin d’article. Quand le nombre d’illustration est vraiment important, est-ce toujours la meilleur solution de mettre en un seul fichier ? Il me semblait avoir entendu que c’est parfois plus rapide au final d’utiliser deux ou trois image (regroupées en fonction des codes couleurs principaux de chaque élément).
    Avez vous des retours d’expériences à ce sujet ?
    Merci
    http://www.legraindeweb.fr/

  • VisiClic Le 6 décembre 2012 à 00:23

    Merci j’ai eu de la difficulté a appliquer mes sprites sur une image actif au survol entre l’article et les commentaires j’ai enfin reussi a appliquer tout ca sur mon blog.. ouffff : )

  • Steph Le 23 février 2013 à 12:48

    Je me décide à intégrer (enfin) du sprite sur mon site, et je dois dire que cela n’est pas forcément simple.
    Je ne vois pas encore l’effet au niveau des performances, mais si cela diminue les requêtes au serveur, alors tant mieux.

  • Dextarian Le 25 janvier 2014 à 02:17

    Je commence timidement à faire un peu de sprite. Le gain est vraiment intéressant. Pour les effets sans Js, ça sera l’étape d’après.

Vos commentaires

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?
Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Suivre les commentaires : RSS 2.0 | Atom