Le format d'image SVG est un format d'image vectoriel qui est maintenant supporté par tous les navigateurs modernes. Il est très adapté pour la création d'icônes ou de petites illustrations. Avec la multiplication des écrans retina (et bientôt 4K) avoir un format d'image vectoriel est idéal, car il pourra être agrandi sans perte de qualité.

Vecto quoi ?

Avant de parler de l'utilisation du format SVG, il est important de comprendre la différence par rapport à des formats plus traditionnels. Dans une image JPG ou PNG on va sauvegarder la couleur des différents pixels qui la compose. Du coup si on augmente la taille d'une image le navigateur va interpoler les pixels manquant en faisant une moyenne par rapport au pixel original. C'est ce qui donne cette impression d'image floutée lorsque l'on agrandit une image.

Le format vectoriel va sauvegarder les informations différemment un utilisant des formes géométriques et des courbes. L'avantage est alors que l'on peut redimensionner l'image à volonté, il suffit d'adapter les valeurs des formes en fonctions du niveau de zoom voulu. Attention cependant, il n'est pas possible d'utiliser le format SVG pour sauvegarder une photo par exemple, car nous ne pouvons pas représenter l'image avec des formes simples.

Du coup le format est idéal pour créer des icônes qui sont souvent basées sur des tracés.

SVG & XML sont sur un bateau

Si vous essayez d'ouvrir un SVG avec un éditeur de texte, vous remarquerez assez rapidement que le code ne vous est pas étranger. En effet, le format SVG est basé sur le format XML. La balise svg caractérise le document (zone de travail et schéma), et à l'intérieur on retrouve nos différentes formes géométriques.

<svg version="1.2" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 82.5 82.5" xml:space="preserve">
<circle fill-rule="evenodd" fill="none" stroke="currentColor" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" cx="41.3" cy="41.3" r="37.8"/>
<g>
  <line fill-rule="evenodd" fill="none" stroke="currentColor" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="25.8" y1="41.3" x2="56.8" y2="41.3"/>
  <line fill-rule="evenodd" fill="none" stroke="currentColor" stroke-width="7" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" x1="41.3" y1="56.8" x2="41.3" y2="25.8"/>
</g>
</svg>

Maintenant se pose la problématique de l'utilisation.

Comment utiliser un SVG ?

Il existe de nombreuses manières d'utiliser les SVG et il est important de comprendre les avantages et les inconvénients de ces méthodes pour adapter votre méthode suivant les cas

IMG et Background

Cela parait évident, mais un SVG peut être utilisé comme tous les autres formats d'image. En utilisant la balise <img> ou la propriété CSS background. Cette méthode permet de charger des SVG qui seront scalable à volonté. Par contre on perd un aspect intéressant qui est la personnalisation. En effet, si on souhaite utiliser 2 fois un même SVG, mais avec des couleurs différentes, on ne pourra pas le faire et il faudra créer 2 versions du même SVG.

Directement dans le code

Le format SVG étant du XML on peut directement l'insérer dans notre code HTML. L'avantage c'est que l'on aura alors accès aux différents composants de notre image depuis le CSS et on pourra modifier la couleur de remplissage ou la couleur de contour facilement. On pourra même utiliser des classes et des groupes pour mieux organiser notre style.

Attention à bien mettre un attribut ViewBox à votre SVG. Cet attribut permet de définir la zone de votre dessin vectoriel et servira de base pour les calculs de redimensionnement. Si vous essayez de changer la width ou height d'un SVG sans ViewBox le dessin sera simplement croppé.

L'inconvénient de cette méthode est que notre SVG se trouve directement dans notre code HTML du coup on alourdit nos pages, on ne peut pas modifier facilement le SVG et on ne profite pas de la mise en cache des navigateurs

La sprite SVG

Comme pour les PNG il est possible de faire un sprite de SVG en créant une grande image que l'on va placer avec le background et background-position. On se retrouvera alors avec le même problème du manque de personnalisation. Mais il existe une solution alternative qui permet de résoudre le problème d'une manière bien plus élégante.

Symbol

La balise symbol permet de définir au sein d'un même SVG un élément graphique que l'on pourra réutiliser. L'avantage est que ce symbole possédera sa propre viewBox. On pourra ainsi avoir un seul fichier qui regroupera l'ensemble de nos illustrations dans des symboles identifiés par des ID.

<symbol viewBox="0 0 448.565 448.565" id="accessory127">
 ... notre dessin
</symbol>

Il est alors possible d'inclure ce symbol en utilisant un <use>

<svg class="star">
 <use xlink:href="sprite.svg#star">
</svg>

Le use peut être utilisé pour charger un symbole qui se trouve même dans un SVG externe. Cette méthode de chargement ne marche pas pour tous les navigateurs, mais vous pouvez utiliser le polyfill svg4everybody qui permet de contrebalancer cette problématique. En revanche, cette méthode de chargement contient malheureusement un inconvénient qu'il faut comprendre pour arriver à utiliser les sprites map en toute quiétude.

use et shadow dom

Le SVG chargé en utilisant le use sera chargé dans le shadow dom et il ne sera donc pas possible de modifier son apparence en CSS. En revanche, si aucun style n'est défini directement dans le SVG ainsi chargé, il héritera alors des règles de l'élément parent. Ainsi, en préparant vos SVG convenablement il est possible d'utiliser la technique du sprite tout en ayant une marge de manoeuvre suffisante pour personnaliser les SVG en CSS. Par exemple en mettant une couleur de tracé à currentColor le tracé prendra automatiquement la couleur de la police du parent.

Automatiser avec GULP

Créer un sprite SVG est relativement long, mais rassurez-vous il est tout à fait possible d'automatiser la création de notre sprite en utilisant gulp et gulp-svg-sprite. Il est possible avec ces outils de générer toutes sortent de sprite SVG, se vous renvoie sur la documentation pour plus d'informations. Dans notre cas on souhaite seulement prendre tous les SVG d'un dossier et en faire un sprite en utilisant les symboles.

var gulp = require('gulp');
var $ = require('gulp-load-plugins')();

gulp.task('svg', function(){
  return gulp.src('./icons/*.svg')
    .pipe($.plumber())
    .pipe($.svgSprite({
      mode: {
        symbol: {
          dest: './',
          sprite: 'sprite.svg'
        }
      }
    }))
    .pipe(gulp.dest('./'));
})

Et voilà le tour est joué !