Les sprites CSS

Les sprites CSS

Les sprites CSS

Le temps des onmouseover, des images préchargées via JavaScript et des autres joyeusetés héritées des grandes périodes de tag soup est, comme le temps des Elfes de la Terre du Milieu, définitivement révolu : faire des effets de rollover sur des images est tout à fait possible en utilisant uniquement les CSS.

Tutoriel par Nico3333fr (Développeur/Intégrateur web, France voisine de Genève)
Mis à jour le 13 Août 2010. 81600 lectures.
Tags : css, rollover, sprite, sprites

La technique 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.

Attention : la technique exposée dans ce tutoriel est à manier avec précaution car elle peut engendrer des problèmes d’accessibilité (typiquement lorsque les images ne sont pas actives). Il est donc déconseillé de l’employer pour des images dont le contenu est pertinent (menu par exemple).

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énements comme onmouseover pour déclencher l’effet survolé (en CSS),
  • dans les cas de recherche de performances ou d’optimisations pointues, quelques astuces permettent d’obtenir des résultats très intéressants en réduisant le nombre de requêtes au serveur pour afficher plusieurs images,
  • comme ces techniques se basent sur XHTML 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.

Par exemple vous pourrez stocker de la sorte dans le même fichier les différents onglets d’un menu de navigation graphique, tel que celui qu’on retrouve sur La Gazette des Communes :

Sprites pour menu

Des sites à fort trafic (Youtube, Google, Facebook, Amazon, …) exploitent cette technique sur des pages que vous consultez tous les jours :

Sprites sur grands sites

La technique des sprites CSS

Approche de base (sans sprite)

L’idée est de n’utiliser que XHTML/CSS pour mettre en forme un lien. En partant de l’idée somme toute logique que le lien en question possède une image en état normal et une autre en état survolé, voici ce que cela pourrait donner :

<!-- pour le XHTML --> <a href="#" title="L'édito" id="editorial"><span>L'édito</span></a> 
/** pour la CSS **/ #editorial{   display:block;   width:80px;   height:31px;   background:url(edito_normal.jpg) 0 0 no-repeat; } #editorial:hover,#editorial:active,#editorial:focus{   background:url(edito_survole.jpg) 0 0 no-repeat; } #editorial span{   text-indent: -5000px; } 

La technique semble naturelle… seul souci, l’appel au fichier edito_survole.jpg se fait au moment du survol sur le lien. Il en résulte un « clignotement », ou un délai d’apparition sur certains navigateurs, selon le temps de chargement. Cette technique, bien que naturelle, est donc à oublier.

Principe (avec sprite)

C’est là que les sprites CSS entrent en jeu, l’idée va être la suivante :

Partie affichée de l'image de l'édito

  • les deux images de fond (état normal et état survolé) seront combinées en une seule,
  • seule la partie haute de l’image va être affichée grâce à background (ci-contre encadrée en rouge),
  • l’image de fond du lien sera simplement décalée lorsqu’on la survole avec la souris grâce à background-position.
<!-- pour le XHTML --> <a href="#" title="L'édito" id="editorial"><span>L'édito</span></a> 
/** pour la CSS **/ #editorial{   display:block;   width:80px;   height:31px;   background:url("editorial.jpg") 0 0 no-repeat; } /* on décale l'image de fond de la hauteur du lien, soit 31 px */ #editorial:hover,#editorial:active,#editorial:focus{   background-position:0 -31px; } /* permet de cacher le texte du lien */ #editorial span{   text-indent: -5000px; } 

On affiche en background les premiers 31 pixels du haut de l’image (l’état normal du lien), et on décale l’image grâce à background-position pour faire apparaître celle en-dessous.

Le décalage étant instantané, l’illusion est parfaite, comme le montre l’exemple n°1.

Pousser la logique de la technique des sprites à l’extrême : quête de performance

Les extensions apôtres de la performance des sites que sont Google Page Speed et Yahoo Yslow vous l’indiqueront : il faut autant que possible minimiser les requêtes HTTP. Autrement dit, il faut essayer de charger le moins de fichiers possible. Certes les sprites CSS permettent de n’avoir qu’une image par lien au lieu de deux (état normal et survolé), mais cela fait quand même 10 fichiers images à charger si vous avez 10 liens… et donc 10 requêtes HTTP GET pour chaque image. Même si les connexions ADSL actuelles sont très performantes, il est légitime de penser à améliorer la vitesse de chargement sur les petites connexions, les Smartphones, etc. Le gain sera toujours appréciable entre le temps mis par le navigateur pour formuler la requête et l’affichage de l’image.

L’idée des sprites CSS peut alors être poussée à l’extrême : nous allons combiner les 10 images de liens d’un bandeau… en une seule.

<!-- pour le XHTML --> <div id="bandeau"> <div id="menugauche">  <ul>   <li><a href="#" id="cv"><span>CV</span></a></li>   <li><a href="#" id="edito"><span>Edito</span></a></li>   <li><a href="#" id="skins"><span>Skins</span></a></li>   <li><a href="#" id="newsweblog"><span>Weblog</span></a></li>   <li><a href="#" id="realweb"><span>Réalisations</span></a></li>  </ul> </div> <div id="menudroite">  <ul>   <li><a href="#" id="liens"><span>Liens</span></a></li>   <li><a href="#" id="terragen"><span>Terragen 2</span></a></li>   <li><a href="#" id="animations"><span>Animations</span></a></li>   <li><a href="#" id="photonum"><span>Photo numérique</span></a></li>   <li><a href="#" id="plansite"><span>Plan du site/Contact</span></a></li>  </ul> </div> </div> 

Construisons la CSS petit à petit, je ne mettrai que les propriétés réellement utiles à la compréhension, la totalité du code est donnée dans l’exemple.

#bandeau{   background:url("top.jpg") 0 0 no-repeat;   width:980px;   padding:0; } 

La div bandeau prend donc l’image de fond, jusqu’ici rien de bien extraordinaire.

#menugauche span,#menudroite span{   text-indent: -5000px; } #menugauche ul,#menudroite ul{   list-style-type:none;   margin:0;   padding:0;   border:0; } #menugauche li,#menudroite li{   margin:0;   padding:0; } 

Ensuite, on fait disparaître les textes des liens pour n’afficher que les images de fond, et on fixe à 0 toutes les marges et autres paddings des divers éléments.

#menugauche li a,#menudroite li a{   position:absolute;   top:36px;   left:30px;   display:block;   height:52px;   width:92px;   background:url("bandeau.jpg") no-repeat;   margin:0;   border:0; } 

Ici nous définissons les propriétés communes à tous les liens du bandeau, afin de factoriser la CSS : les liens seront donc positionnés en absolu, auront tous la même image bandeau.jpg en fond (état normal comme survolé, tous sont inclus dedans), auront tous la même taille et hauteur. Seul le positionnement des liens et de l’image de fond va différer pour chacun.

#menugauche #cv{   background-position:2px 0; } #menugauche #cv:hover,#menugauche #cv:active,#menugauche #cv:focus{   background-position:2px -52px; } #menugauche #edito{   left:122px;   background-position:-89px 0; } #menugauche #edito:hover, #menugauche #edito:active, #menugauche #edito:focus{   background-position:-89px -52px; } /* etc... */ 

Le premier lien est positionné (il garde dejà les propriétés left:30px et top:36px définies plus haut dans les propriétés communes aux liens. Le suivant est décalé à droite et a son background décalé, l’effet de rollover étant aussi assuré par un décalage (celui du lien en état normal sur l’axe x, et le lien en état survolé sur l’axe y).

Le décalage étant toujours instantané, l’illusion est parfaite, comme on peut le constater sur l’exemple n°2.

Les avantages sont indéniables en termes de performances : une seule image permet de charger tous les liens de mon bandeau. Si vous généralisez le concept comme je l’ai fait pour intégrer le design de mon site dont sont tirés ces exemples :

  • Les liens du bandeau utilisent donc une seule image au lieu de 10 !
  • 12 images pour mes titres h1 sont combinées en une seule image, qui plus est, cette image se prête bien au format GIF : 26,2 Ko pour 12 titres en image, c’est plutôt appréciable !
  • Avantage supplémentaire : le temps de chargement du graphisme sera instantané pour les autres pages, l’image des h1 ayant déjà été chargée.
  • Au final, la totalité du graphisme se charge en seulement 6 images au lieu de 26.

Inconvénients

Néanmoins, la technique des sprites CSS poussée à l’extrême présente quelques inconvénients :

  • Si l’on doit changer une image d’un unique lien du bandeau, il faut rechanger et ré-exporter toute l’image au lieu d’une seule.
  • La feuille de style CSS sera un petit peu plus lourde.
  • Le positionnement peut être ardu si vous devez comme dans mon cas positionner au pixel près pour que les divers fonds soient parfaitement raccordés.

L’essentiel est de savoir à quel niveau s’arrêter : si le temps d’intégration et/ou de maintenance explose littéralement les bénéfices en termes de performances, autant revenir à la méthode classique. Bien entendu, ne se pose pas le problème de temps si vous faites votre intégration CSS à temps perdu. Toutefois, certains cas peuvent vous permettre de passer outre cette complexité… certaines fois en améliorant encore les performances de votre intégration. Jetons un oeil à ces astuces.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *