Réflexions sur la minification CSS
29 juillet 2010Quand il s’agit de compresser les données envoyées au client, j’ai l’impression que la minification CSS est le plus délaissé des minificateurs. Alors que les outils JavaScript poussent le concept très loin (Closure Compiler, Caja…), il reste encore des points à explorer lorsqu’il s’agit de minifier les feuilles de style.
Les techniques existantes
Les meilleurs minifieurs CSS implémentent déjà les opérations suivantes.
Supprimer les espaces blancs et les caractères superflus
- Espaces blancs
- Dernier point virgule d’une déclaration
- Unités de mesure pour les valeurs à 0 (ex: margin:0px -> margin:0)
- Commentaires (tout en préservant les hack CSS)
- Les déclarations vides (ex : p {})
Utiliser les propriétés sténographiques
- margin
- padding
- border
- outline
- font
- list-style
- background (notamment à la place de background-color)
Ces propriétés sont plus courtes et peuvent être utilisées pour définir d’un coup plusieurs propriétés (ex : margin permet de se passer de margin-right, margin-top, margin-left et margin-bottom).
Compresser les couleurs
Utiliser les notations courtes des couleurs hexadécimales (Ex: color:#ff6600 devient color:#f60;). Utiliser les couleurs supportées en CSS 2 dont le nom est plus court que la notation hexadécimale. Voici la liste des couleurs dans ce cas :
Hex | Nom | Couleur | Hex court |
---|---|---|---|
#800000 | maroon | #800000 | |
#ff0000 | red | #f00 | |
#ffA500 | orange | #ffA500 | |
#808000 | olive | #808000 | |
#800080 | purple | #800080 | |
#008000 | green | #008000 | |
#000080 | navy | #000080 | |
#008080 | teal | #008080 | |
#c0c0c0 | silver | #c0c0c0 | |
#808080 | gray | #808080 |
CSSTidy prend déjà en charge ces remplacements, mais il ne supporte pas les couleurs SVG, pourtant implémentées dans un grand nombre de navigateurs (dont IE6, exception faite des couleurs contenant « gray »).
Fusionner les sélecteurs identiques
Deux sélecteurs semblables peuvent être fusionnés. Ex:
h1 {font-weight:normal} p {margin:0} h1 {color:orange}
peut être remplacé par :
h1 {font-weight:normal;color:orange} p {margin:0}
Parmi les exceptions, il y a les déclarations @font-face dont plusieurs peuvent coexister cote à cote. CSSTidy fusionne les @font-face, attention donc à la remettre à la main si vous l’utilisez.
Des voies à exploiter
Avec ces techniques, vos feuilles de style peuvent gagner en moyenne 50% du poids si elles sont formatées sous Eclipse (Ctrl + Alt + F), par exemple. C’est déjà bien, mais il reste quelques voies à exploiter.
Améliorer la compression Gzip
Je me demande à quel point le tri des propriétés CSS au sein des déclarations peut faire gagner du poids lors de la minification CSS. Ce conseil est inspiré de la minification HTML de Page Speed. Si les propriétés se retrouvent dans le même ordre le long des déclarations, il est probable que des motifs textuels récurrents soit plus nombreux et que le taux de compression gzip en soit amélioré.
L’idéal serait de tester le poids Gzippé de quelques combinaisons (tri selon les propriétés en ordre alphabétique, alphabétique inversé, tri selon les valeurs des priorités…), puis de choisir la plus performante.
Guide des bonnes pratiques pour une meilleure compression Gzip
On trouve beaucoup de ressources sur les bonnes pratiques pour écrire du code JavaScript minifier-friendly. Mais il n’existe, à ma connaissance, rien de tel pour le CSS.
Un tel guide devrait conseiller, par exemple, le recours systématique aux propriétés sténographiques (ex : ne jamais utiliser margin-bottom, mais margin à la place), même si cela implique de redéfinir toutes les propriétés de ce sélecteur. Bref, toutes les opérations qui peuvent faire gagner du poids mais qui ne sont pas automatisables par le minificateur.
Minification CSS avec perte et HTML-aware
Enfin, j’aimerais qu’un minifieur CSS me donne la possibilité de générer une feuille de style la plus compressée possible, quitte à perdre de l’information. Voici quelques idées :
- Il devrait pouvoir subtiliser des couleurs courtes à des couleurs dont la notation est plus longue, tout en restant visuellement proche.
- Il devrait forcer le recours aux notations sténographiques en indiquant des valeurs par défaut pour les valeurs manquantes (ex: remplacer padding-bottom:15px; par padding:0 0 15px;).
- Réorganiser les sélecteurs ayant des règles communes pour les regrouper si le résultat est moins lourd.
- Supprimer les hacks CSS s’ils prennent trop de place.
Enfin, j’apprécierais qu’il propose des optimisations en utilisant l’HTML sur lequel est appliquée la feuille de style. Par exemple, il pourrait remonter des propriétés communes à toutes les balises enfants vers leur balise parent.
Ce serait bien pratique de disposer d’un tel outil au moment de l’intégration HTML, même si cela implique de revoir un peu la maquette par la suite.
Quelques outils
PHP
CSSTidy : outil très complet. Contrairement aux autres il s’agit d’un véritable parser CSS. Il a tout de même quelques limitations évoquées plus haut dans ce billet.
Minify : contient parmi ses outils un minificateur CSS.
Java
YUI Compressor : comme Minifiy, un compresseur JS/CSS made in Yahoo!
En ligne
http://www.cleancss.com/ : demo en ligne de CSSTidy.
http://iceyboard.no-ip.org/projects/css_compressor/ : très complet également. Il ne fusionne pas les propriétés sténographiques.
La stratégie de minification de GitHub :
http://github.com/blog/551-optimizing-asset-bundling-and-serving-with-rails
C’est du ruby. Mais ça doit être assez aisément adaptable dans un autre langage.
[...] Pour les CSS, à nouveau énormément de compresseurs en ligne. Il n’y en a pas un qui sort du lot, ils ont tous à peu près le même résultat. Vous pouvez également aller voir sur cet article intéressant proposant une réflexion plus approfondie sur la compression CSS : http://optimisationweb.fr/2010/07/reflexions-minification-css.html [...]
avec gzip on gagne déjà 80% sur le fichier original
avec les minifications JS, on peut gagner 50% sur le fichier original ce qui est beaucoup, mais ajouté à gzip on ne passe jamais que de 80% à 90% de gain.
Hors pour CSS on ne gagne pas beaucoup : je n’ai pas vu beaucoup de chiffres mais on doit tourner à moins de 20%.
Est ce que ça vaut le coup de choisir des compresseurs très agressifs potentiellement destructeurs pour passer de 80% à 84% de compression ?
En fait il serait mieux de parler de « Faciliter la compression Gzip » au lieu de parler d’ « Améliorer la compression Gzip ».
Enfin « Il devrait pouvoir subtiliser des couleurs courtes à des couleurs dont la notation est plus longue, tout en restant visuellement proche. » pourrait poser problème par exemple dans la légende d’une carte où la carte ne serait pas modifiée. Or malheureusement de nombreux couleurs très très proches peuvent être utilisée dans une carte.
@Manu1400 : L’idée serait de subtiliser des couleurs proches le plus haut possible dans la chaine de prod. L’idéal étant que les graphistes choisissent des couleurs qui compressent bien pour les aplats ou titres qui seront créés en CSS.
Mais comme le dit JPV, la mise en application de telles techniques n’a que peu d’intérêt. Pour moi ça vaut le coup, par exemple, quand les CSS ne sont pas volontairement cachés (AJAX ou inline)…