Créer un Sprite CSS

Créer un Sprite CSS

Cet article ne va intéresser qu’une poignée d’intégrateurs, fleuron de l’optimisation des temps de chargement, ayatollahs de la Webperf et autres fascistes râleurs dès qu’une page met plus d’une seconde à charger.

Rassurez-vous, j’en fais moi-même parti (c’est une bonne maladie, je le vis très bien).

Aujourd’hui, on voit une technique d’un autre temps, mais qui peut encore servir : le Sprite CSS. Pour les acharnés, le lien vers la doc de la W3 Schools.

Un Sprite CSS, c’est quoi ?

Un Sprite CSS, c’est une technique qui consiste à regrouper les images de fond sur un même fichier, pour éviter d’avoir trop d’appels HTTP sur le chargement d’une page. C’est surtout pertinent pour les sites qui sont en HTTP1. Rappel : HTTP2 est beaucoup plus rapide que HTTP1, permet de paralléliser les chargements de contenus, et est donc moins sensible à un grand nombre de fichiers pour composer une page.

Tant qu’on est à souligner la quasi-obsolescence de cette technique, on peut également évoquer toutes les évolutions qu’il y a eu au niveau CSS pour générer des fonds en dégradé complexe, mettre des images de fond en base 64, utiliser des librairies d’icônes etc.

Cependant, on peut encore utiliser ce genre de technique pour gratter quelques centaines de milliers de secondes sur les pages où on a des images de fond (je vous avais prévenu, c’est pour les psychopathes).

Comment faire un Sprite CSS

On va prendre un exemple tout bête : les images de fond que j’utilise sur digital-cookie.io

Sur les pages profondes, celles qui sont surtout là pour taper sur la longue traine, j’ai plusieurs petites images de fond qui me serve à découper mes sections de page, rajouter des marqueurs autour des titres etc.

Vous trouverez ci-dessous le visuel qui contient ces images.

Ici, j’ai bien un seul fichier pour afficher 7 images différentes (donc un appel HTTP au lieu de 7).

On va prendre l’exemple des titres de niveau deux (H2). Les petites icônes de part et d’autre du titre sont intégrées grâce à une image de fond, en utilisant la pseudo classe «:before » et «:after » de CSS3.

Dans un premier temps, on va positionner ces éléments de part et d’autre du titre. Du coup, on commence par positionner le titre lui-même grâce aux codes suivants :

.gdm-ez-container h2 {
  position: relative;
  display: inline-block;
}

Le titre est en « display:inline-block; » pour qu’il ne s’étale pas sur toute la largeur de la page dont l’overflow est en display:none (ça positionnerait mes images de fond hors du conteneur principal donc on ne les verrait pas) , et la position relative, c’est parce que mon « before » et mon « after » vont être en position absolue.

La suite coule de source :

.gdm-ez-container h2::before,
.gdm-ez-container h2::after {
  /*On ne veut l’image de fond qu’une seule fois*/
  background-repeat: no-repeat;
  /*On indique l’adresse de l’image de fond*/
  background-image: url("/wp-content/uploads/separator.png");
  /*On déclare la largeur et la hauteur de ma « fenêtre » de contenu*/
  width: 40px;
  height: 25px;
  /*On joue la facilité en positionnant l’élément en absolue */
  position: absolute;
  /*On déclare un contenu sinon on n’aura rien */
  content: "";
}

Et enfin, on positionne l’image de fond :

.gdm-ez-container h2::before {
  /*On positionne le « before » en lui-même */
  top: 7px;
  left: -66px;
  /*On positionne le background */
  background-position: 0 -31px;
}

On fait la même chose pour le after (et toutes les autres images qui sont contenues dans le Sprite).

A noter, pour ne pas se retrouver avec des centaines de lignes de code, qu’on peut factoriser les déclarations en regroupant les éléments de manière optimisée (c’est compliqué mais c’est plus propre).

En utilisant un Sprite CSS, j’ai 6 appels HTTP en moins sur ma page. Et là, c’est un petit sprite, car j’avais peu de besoins. Si vous avez beaucoup d’images de fond, cette technique est  redoutable d’efficacité.

Un autre exemple avec des boutons

Prenez les deux énormes boutons ci-dessous :

Envoyer

J’aime

Le code source des boutons est simplissime :

<a class="sendex" href="#">Envoyer</a>
<a class="megusta" href="#">J'aime</a>

Le CSS, lui, est un peu plus complexe :

.sendex,
.megusta {
  display: inline-block;
  font-weight: bold;
  color: white;
  padding: 25px 25px 25px 65px;
  border: solid 3px white;
  border-radius: 6px;
  /*ON RAJOUTE UNE OMBRE PORTEE POUR VOIR LES BORDS BLANCS SUR FOND BLANC*/
  -webkit-box-shadow: 0px 0px 32px -7px rgba(0, 0, 0, 0.61);
  -moz-box-shadow: 0px 0px 32px -7px rgba(0, 0, 0, 0.61);
  box-shadow: 0px 0px 32px -7px rgba(0, 0, 0, 0.61);
  font-size: 42px;
  text-transform: uppercase;
  box-sizing: border-box;
  -moz-box-sizing: border-box;
  -webkit-box-sizing: border-box;
}

Quand vous créez votre sprite pour une image de fond comme on a ici, faites bien attention à la hauteur du bouton ! Utilisez la console de développeur pour avoir la hauteur précise, ou bien utilisez la formule suivante :

(Font-size X line-height) + padding + border = Height

Ici, j’ai « calé » les hauteurs avec le padding. Mais si vous voulez préciser la hauteur dans le CSS, pensez à utiliser la propriété box-sizing. Anticiper sur le calcul de la hauteur doit vous permettre de positionner les composants de votre sprite sur le fichier parent (le PSD). Voir ci-dessous le fichier du sprite :

Puis on déclare les couleurs de fond et on place les images de fond, pour l’état standard et le hover :

.sendex {
  background: url("/img/sprite-ex.png") no-repeat #00697f;
  background-position: 17px 21px;
}
.megusta {
  background: url("/img/sprite-ex.png") no-repeat #3a559f;
  background-position: 12px -112px;
}
.sendex:hover {
  background: url("/img/sprite-ex.png") no-repeat #ffc600;
  background-position: 17px -46px;
}
.megusta:hover {
  background: url("/img/sprite-ex.png") no-repeat #2cb2ff;
  background-position: 12px -179px;
}

J’aurai pu factoriser en déclarant à part « background-color », « background-image » , « background-repeat » et « background -position » mais pas sur que ça aurait fait beaucoup moins de code… Donc j’ai fait au plus simple (et au plus rapide). Le code n’étant pas dans le CSS principal, c’est pas bien grave si c’est pas optimisé à fond.

Transitions et hover

Vous pouvez également utiliser un Sprite CSS pour générer vos images de fond sur un survol de boutons ou de conteneurs, comme dans l’exemple. Vous devez en revanche savoir que pour gérer les transitions, ça va devenir nettement plus complexe qu’un simple :

.montruc :hover {
  transition : 300ms ease all;
}

Car ici, vous allez devoir, justement, préciser ce que vous souhaitez modifier dans la transition (pour ne pas voir de mouvement opéré sur l’image de fond).

.sendex,
.megusta,
.sendex:hover,
.megusta:hover {
  /*Ici, on verra justement le va et vient entre les images de fond*/
  transition: 0.3s ease all;
}
.sendex,
.megusta,
.sendex:hover,
.megusta:hover {
  /*Ici, en revanche, seul la couleur du texte et la couleur de fond sont prise en compte dans la transition*/
  transition:
    color 0.3s ease,
    background-color 0.3s ease;
}

J’ai écrasé la transition 300ms ease all pour la démo sur la vidéo.

Utiliser un générateur de Sprite CSS

On trouve des générateurs de Sprite CSS sur le Web, mais pour être honnête, à chaque fois que j’ai essayée d’en utiliser un, ça ne marchait pas comme je voulais. Du coup, ça va plus vite de le faire à la main, mais générateur peut vous aider à vous inspirer.

L’avenir du sprite CSS ?

Dans de nombreux cas, on préférera utiliser des icônes pour les images de fond, des formats vectorisés comme le svg ou du code pur… Vous avez compris que la technique du Sprite peut être amenée à disparaître assez rapidement, mais elle doit quand même rester dans la boîte à outils d’un bon intégrateur (soucieux de conserver une note correcte des audits de temps de chargement). Dans un prochain tuto, justement, je vous montrerai comment intégrer une librairie d’icones (au format typo web ou svg).

Charles Annoni

Charles Annoni

Développeur Front-End et Formateur

Charles Annoni accompagne les entreprises dans leur développement sur le web depuis 2008. Il est également formateur dans l’enseignement supérieur.