Sur le projet sur lequel je travaille actuellement, j'ai dû me coltiner la gestion de sprites CSS optimisés pour des écrans Retina, et surtout en grand nombre et dans plusieurs formats différents (genre 80 icônes avec leur version survolée et encore un troisième état, que nous appellerons « actif »).
Autant le dire, cet aspect du projet est plutôt rébarbatif, et les fonctions « magiques » de Sass de gestion des sprites m'ont vite montré leurs limites (ou les limites de mes connaissances en Sass se sont vite montrées me dira un expert en Sass :) ). En tout cas, cela ne convenait pas à mon cas.
Finalement, pour des icônes toutes semblables de ce genre (j'ai juste ajouté un fond au lieu de la transparence) :
Voici l'approche que j'ai prise : d'abord une classe générale qui contient toutes les propriétés communes qui permettra de factoriser et ensuite chaque classe de chaque icône qui décale l'image de fond pour afficher la bonne image. Chaque icône dans ce sprite fait 48 pixels de large, pour un affichage de 24 pixels donc (optimisé Retina). Les icônes sont côte à côte par rangs de 10.
Seulement, gérer cela à la main avec 6 icônes, pas de souci, mais pour plus de 80 icônes, c'est hors de question.
Bref, j'ai bricolé une fonction Sass qui ressemble à cela :
// ici les propriétés générales
.icon-service-general {
background-image: url('../../layout/images/icon-services-48.png');
background-repeat: no-repeat;
display: inline-block;
width: 24px;
height: 24px;
background-size: 240px 576px;
/* la moitié des dimensions de l'image du sprite : optimisation retina */
}
$x: 0;
$y: 0;
$grid: 24px;
// là je limite la liste pour l'exemple
@each $service in performance, motion, presentations, etc. {
// on factorise avec la classe « général »
.icon-service-#{$service} {
@extend .icon-service-general;
}
// je décale de tant de fois la grille
.icon-service-#{$service} {
background-position: ( -( $x * $grid ) ) ( -( $y * $grid ) );
}
// idem pour le rollover
a:hover .icon-service-#{$service},
a:active .icon-service-#{$service},
a:focus .icon-service-#{$service} {
background-position: ( - ($x * $grid) ) ( -( $y + 1) * $grid );
}
$x: $x+1;
@if $x == 10 {
// la taille de la grille = 10 icônes côte à côte
$x: 0;
$y: $y+3; // de 3 (fois la grille) en 3
}
// etc .
}
Ce qui va générer la CSS suivante :
// ici les propriétés générales
.icon-service-general, .icon-service-performance, etc. {
// ici les propriétés communes
}
.icon-service-performance {
background-position: 0px 0px;
}
a:hover .icon-service-performance,
a:active .icon-service-performance,
a:focus .icon-service-performance {
background-position: 0px -24px;
}
/* etc. */
Le gros avantage, c'est que c'est facilement adaptable à une grille d'icônes de n'importe quelle largeur, Retina ou non. Et surtout, ça fait le sale boulot tout seul.
Bref, bien travailler pour moins travailler.
en passant je te reparle de grunticon, il faudra bien que tu testes un jour ; )
Avec des icones en svg un drag & drop de tes icones sur grumpicon.com tu aurais obtenu les fichiers css qui vont bien :
- un pour les navigateurs qui supportent svg
- un pour navigateurs qui supportent png en base64
- un pour navigateurs qui ne supportent ni l'un ni l'autre, avec les icones en png
un petit script js qui détecte le support de svg (et base64) et fournit le bon fichier css.
Avantages :
- pas de boulot côté css ou prépro
- pour svg (et png base64) une seule requête comme la sprite
- requête non bloquante
- un bien meilleur support que les icon font (autre solution possible mais tu laisses du monde sur le carreau)
- svg et retina font bon ménage
Have a look ; )