· Tech watch

Utiliser, optimiser et servir des fichiers SVG

SVG est un format d’images vectorielles qui repose sur une syntaxe XML. Il est actuellement supporté par tous les navigateurs du marché, y compris Internet Explorer depuis sa version 9. Le support de ce format s’améliorant rapidement, il devient de plus en plus utilisé. Ceci dit, le fait que ce format repose sur XML nécessite de prendre quelques précautions en termes de performance.

Rappel : Inclure du SVG dans du HTML

Si SVG peut se suffire à lui-même, le Web design moderne en fait une utilisation importante en conjonction avec les autres technologies Web que sont HTML, CSS et Javascript (à titre d’exemple, jetez donc un coup d’œil au site Vlog.it). Ainsi, avant de voir comment on optimise SVG, faisons d’abord un petit rappel sur les différentes façons d’inclure du SVG dans un document HTML.

Avec HTML, vous disposez de 4 techniques pour inclure du SVG dans le document :

-# la balise iframe,
-# la balise object,
-# la balise img
-# et, avec l’arrivée de HTML5, vous pouvez aussi mettre des balises svg directement dans du HTML.

Historiquement et techniquement, c’est la balise object qui est la plus sûre et la plus appropriée pour inclure du SVG. Elle vous permet d’éviter tous les effets de bord liés aux iframe (performances, accessibilité, etc.) tout en autorisant la propagation des événements DOM (ce que ne permet pas la balise img). Cerise sur le gâteau, elle vous permet de gérer élégamment les solutions de repli pour l’accessibilité ou, plus trivialement, de gérer les vieilles versions d’Internet Explorer. En effet, pour mémoire, si l’objet référencé par la balise object n’est pas compris par le navigateur, il affichera le contenu HTML présent à l’intérieur de la balise.

Du côté de CSS, il est possible d’inclure du SVG via :

-# la propriété background-image (extrêmement utile en conjonction avec la nouvelle propriété CSS 3 [background-size->https://developer.mozilla.org/en/CSS/background-size])
-# la propriété content utilisée avec les pseudo-éléments  ::before et  ::after.

Il sera également possible à terme de l’utiliser avec la propriété CSS 3 border-image. Malheureusement, à ce jour, aucun navigateur ne supporte cette propriété correctement, en particulier avec SVG.

En résumé, navigateur par navigateur[[Notez que je ne cite pas Safari, mais c’est la même chose que Chrome. En ce qui concerne IE, il s’agit bien sûr de IE9 ;)]], ça va donner ça :

| Intégration | IE | Firefox | Chrome | Opera |
| iframe | ok | ok | ok | ok |
| object | ok | ok | ok | ok |
| img | ok | ok | ok | ok |
| svg | ok | ok | ok | ok |
| background-image | ok | ok | ok | ok |
| content | ok | ok | ok | ok |
| border-image | non | bug | bug | bug |

On notera un petit bug dans Firefox qui parfois pixelise les images SVG intégrées via CSS ou la balise img.

SVG et performance, les principaux écueils

En terme de performances, SVG souffre de deux écueils qui sont liés au fait que SVG est un format XML.

Premièrement, qui dit XML dit DOM. En effet, tous les navigateurs qui vont interpréter une image SVG vont d’abord construire un arbre DOM des éléments qui constituent cette image. Or, DOM est une API extrêmement lente qui peut consommer beaucoup de mémoire si l’on n’y prend pas garde. Ainsi, plus vous avez d’éléments dans votre image, plus son interprétation aura un impact sur les performances. Dans la mesure du possible, essayez toujours de réduire le nombre d’éléments nécessaires pour construire votre image.

Vous pouvez bien sûr toujours vous amuser à faire cette optimisation à la main, mais de vous à moi, ce n’est pas vraiment super folichon à faire. De ce point de vue, les logiciels de dessin vectoriel comme Adobe Illustrator ou Inkscape peuvent vous aider de manière assez efficace via les fonctions de « pathfinder » pour fusionner des formes entre elles ou via les fonctions de simplification des courbes qui vont vous permettre de réduire le nombre de vecteurs d’une image. L’aspect délicat étant alors de trouver le bon point d’équilibre entre le respect du dessin original et la version optimisée.

Deuxièmement, le format XML est un format texte assez verbeux. Concrètement, cela signifie qu’une image SVG est facilement plus lourde qu’une image bitmap du seul fait de son format natif.

Pour éviter ce problème, il vous faut compresser vos images. SVG supporte très bien la compression avec des résultats parfois spectaculaires (il n’est pas rare de voir des taux de compression de l’ordre de 70 % à 80 % avec une simple compression GZip). Pour cela, vous avez deux options :

  • produire du SVG compressé via GZip (qu’on identifie souvent avec l’extension .svgz au lieu de .svg)
  • demander à votre serveur Web de compresser le SVG à la volée lorsqu’il le sert.

La première option a l’avantage de réduire la consommation de CPU de votre serveur, tout en permettant de compresser le SVG au maximum, car les calculs de compression sont fait avant même la mise en production de vos fichiers.

De son côté, la deuxième option permet de gérer dynamiquement la compression en se basant sur de la négociation de contenu HTTP, afin de toujours servir aux navigateurs un format de compression qu’ils sont capables de gérer (GZip, Deflate, etc.).

En creux, les avantages de la première méthode sont les inconvénients de la seconde, et vice et versa.

Configurez votre serveur

Point essentiel quand on sert des fichiers SVG, vérifiez toujours que votre serveur Web envoie les en-têtes HTTP qui vont bien. En particulier, vérifiez toujours que le type MIME envoyé est bien image/svg+xml. Sans ça, certains navigateurs refuseront tous simplement d’afficher l’image, et les plus taquins vous afficheront un bel arbre XML lambda !

Si vous servez des fichiers compressés avec GZip, pensez bien à envoyer l’en-tête HTTP qui le signale, sinon, là encore, les navigateurs n’afficheront rien et les plus joueurs vous proposeront de télécharger le fichier.

Si vous utilisez le serveur Apache, il suffit d’ajouter ces deux lignes dans la configuration du VirtualHost (ou dans un fichier .htaccess) :


AddType     image/svg+xml  svg svgz
AddEncoding gzip           svgz

Optimiser SVG lui-même

Au niveau du document SVG, il est également possible de réaliser un certain nombre d’optimisations qui peuvent en améliorer les performances.

Un petit avertissement avant de rentrer dans les détails : ces optimisations nécessitent du temps et ne sont pas toujours automatisables. Elles sont donc coûteuses en ressources, or, on sait tous ce que cela implique dans un projet. Prenez donc le temps de peser le pour et le contre avant d’entamer une optimisation du code. Dans la mesure du possible, je vous indiquerai le coût de chacune de ces optimisations.

Réduisez les décimales

Les outils de dessins génèrent souvent des fichiers avec une précision trop importante (parfois plus de 6 chiffres après la virgule pour les valeurs chiffrées). Il est assez facile de réduire cette précision sans perte visuelle (2 à 3 chiffres après la virgule).

Coût de l’optimisation : Faible car facilement automatisable

Supprimez les balises inutiles

Les outils qui génèrent du SVG ont vite tendance à abuser des métadonnées (les balises title, desc, metaData). À moins qu’elles ne soient indispensables pour des questions d’accessibilité ou de référencement, vous pouvez les supprimer sans risque. Le cas des balises g ou svg, qui sont des conteneurs génériques, est un peu plus délicat car leur usage est parfois nécessaire. Il faut donc voir au cas par cas.

Coût de l’optimisation : Moyen, car même si c’est facilement automatisable, une part de travail manuel peut être nécessaire.

Préférez la balise path aux formes de base

La syntaxe de l’attribut d de la balise path est très compacte et s’optimise facilement (en particulier en utilisant les notation de coordonnées relatives), il est donc conseillé de préférer cette balise aux balises des formes de base qui sont souvent plus verbeuses.

Coût de l’optimisation : Élevé, car elle dépend fortement de votre outillage, de votre savoir-faire et du degrés d’optimisation que vous souhaitez atteindre.

Externalisez les attributs de présentation dans des feuilles de style

Certains attributs SVG peuvent s’utiliser comme des propriétés CSS. Ainsi, ils peuvent être facilement externalisés dans des feuilles de styles externes qui seront mises en cache par les navigateurs. Les sélecteurs CSS permettent également de mutualiser facilement les propriétés communes à certains éléments, ce qui limitera la verbosité de SVG.

Coût de l’optimisation : Moyen, car il repose sur le même outillage et le même savoir faire que pour les pages HTML. Cependant, il nécessite d’être bien pris en amont, surtout si vos fichiers SVG sont volumineux ou générés par des éditeurs d’images qui ne connaissent pas CSS.

Conclusion

Comme toute technologie Web, SVG nécessite un savoir-faire qui lui est propre. Ceci étant, en vous reposant sur vos connaissances en HTML/CSS et en suivant les quelques conseil de cet article, vous pourrez rapidement utiliser SVG dans un contexte de production sans avoir à vous soucier des performances. Amusez-vous bien !

4 commentaires

  1. Le SVG peut-être très utile pour un rendu net de pictogrammes sur un site, lorsque celui-ci est affiché sur un écran de type Rétina, où 1 pixel en vaut deux.

    On peut aussi générer des PNG / GIF de remplacement pour les vieux navigateurs ne supportant pas le SVG, avec soit une feuille de style conditionnelle, soit avec Modernizr (ce qui implique par contre l’activation de javascript par le client)

  2. Bonjour,
    Merci pour ce super article.

    J’ai juste une petite question: sait-on pourquoi Firefox pixellise certains SVG? Est-ce du à un NS en particulier? A des attributs non reconnus?

    Vincent

  3. Jérémie Patonnier

    Bonjour Vincent,

    C’est un bug qui n’est pas spécifiquement lié à un élément particulier de SVG mais à la façon qu’a Firefox de traiter globalement les images (en gros, Gecko à été pensé pour traiter uniquement des images resterisées, pas des images vectorielles). Cela va nécessiter la réécriture de pas mal de code dans le moteur de rendu et il n’y a pas vraiment de solution de contournement car le coté « pixelisé » dépend à la fois des proportions de l’image et du niveau de zoom appliqué à celle-ci.

    Le bug est identifié et peut être suivi ici : https://bugzilla.mozilla.org/show_bug.cgi?id=600207

    Si ce bug vous gène dans votre utilisation de SVG, n’hésitez pas à montrer et expliquer (en anglais) vos cas d’usages sur le bug car cela aidera les équipes à prioriser la résolution de ce bug.

  4. Merci pour ces informations, je rédige un cahier des charge sur l’utilisation du SVG, soit sous forme de sprites soit individuellement. actuellement tous le site utilise des éléments individuels png ou jpg avec a la clé une importante charge serveur. Je doit déterminer si le ratio complexité_dom/requête_serveur est en faveur du svg sprite. Dans mes recherche j’ai trouver des outils très utiles pour réduire la taille du svg
    SVGO
    une appli node.js
    il aussi possible d’écrire ses propres plugins pour enrichir et adapter, d’ailleur pour réduire à 3 chiffres après la virgule il y a le plugin «cleanupNumericValues.js»
    Je croit que ce format est pleins de promesse et qu’il vaut vraiment la peine de se pencher sérieusement dessus.
    Cordialement.

Les commentaires sont désormais fermés.