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
onmouseoverpour 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 :