Le SVG, c'est maintenant

À la lecture d’un article sur SVG sur CSS-Tricks, je n’ai pas pu m’empêcher d’écrire ce billet.

L’article est intéressant mais à prendre avec des pincettes. L’auteur y indique différentes façons d’embarquer du SVG sur une page : en utilisant une balise <img>, avec un background-image, en ligne dans le HTML ou en utilisant une balise <object>. Les méthodes décrites sont correctes, mais je trouve la gestion des fallbacks améliorables.

Avant d’utiliser SVG, comme toutes autres fonctionnalités, vous devez être conscient des plateformes qui supportent ce format. Le support est très correct, si ce n’est sous Internet Explorer inférieur à la version 9.

HTML

Vous pouvez utiliser le code HTML le plus simple :

<img width=634" height="557" src="octocat.svg" alt="Octocat, la mascotte de GitHub" />

Octocat, la mascotte de GitHub

Octocat, la mascote de GitHub au format SVG par johan

Tout en gardant à l’esprit que seul le fallback textuel sera fourni sous IE < 9.

L’indication de taille n’est présente que pour aider le navigateur à réserver la place lors du rendu de la page.

Dans l’article de CSS-Tricks, le fallback bitmap est effectué via JavaScript soit en utilisant Modernizr et jQuery, soit avec du JavaScript en ligne (!). Il y a une façon plus simple :

<object width="634" height="557" data="octocat.svg" type="image/xml+svg">
	<img width="634" height="557" src="octocat.png" alt="Octocat, la mascotte de GitHub" />
</object>

Octocat, la mascotte de GitHub

Cette fois, le SVG s’affichera sur les plateformes supportant le type MIME image/xml+svg, sinon la balise <img> s’occupera d’afficher le fallback bitmap. Cependant, je ne sais pas comment un lecteur d’écran va réagir en rencontrant ce type de code.

Webkit semble télécharger le fallback bitmap avant le SVG, ce qui est assez problématique pour les performances.

CSS

Côté CSS, vous avez deux solutions. Soit vous utilisez la détection de fonctionnalité (Modernizr ou autre) :

document.body.className += (document.createElementNS && document.createElementNS(’http://www.w3.org/2000/svg’, ’svg’).createSVGRect ? "" : "no-svg");
Exemple de code permettant de détecter le support du SVG
        #element { background-image: url(octocat.svg); }
.no-svg #element { background-image: url(octocat.png); }
On gère les deux cas : présence ou non de SVG

Soit vous bidouillez en CSS :

#element {
	background-image: url(octocat.png); /* 1) Supporté partout */
	background-image: none, url(octocat.svg); /* 2) Multiple background */
}

Dans cet exemple on fournit le bitmap en premier (1). Puis on définit un multiple background (2) qui ne sera retenu que sur les plateformes supportant cette fonctionnalité. Heureusement, le support de multiple background est assez similaire à celui de SVG.

L’article fait également (trop) mention du SVG en ligne ou d’encodage en base64. Il est vrai que ces techniques réduisent le nombre de requêtes HTTP, mais je trouve que cela nuit trop à la maintenance et devrait faire partie d’un processus automatisé.

Sprites SVG ?

Pour réduire le nombre de requête HTTP nous utilisons des sprites ; une image en contenant d’autres. À y réfléchir, c’est également possible en SVG.

Ne vous emballez pas trop vite, le support des fragments identifiers (la fonctionnalité permettant d’utiliser des sprites SVG) n’est pas bon.

Le fragment identifier vous permet d’afficher une zone ou un élément du SVG .

Prenons ce sprite :

Capture d’écran de l’éditeur utilisé pour créer le SVG.
Le rectangle blanc représente la viewBox ; la partie visible du SVG

Si on essaye d’accéder à ce SVG on obtient un premier « état » :

Maintenant, si dans l’URL de cette ressource on spécifie un fragment décrivant une autre zone à afficher (un autre viewBox) :

Après avoir rajouté le fragment #svgView(viewBox(378, 0, 378, 307)) à l’URL.
Les valeurs numériques représentent respectivement x, y, width et height.
Par rapport au premier « état » nous avons modifié le x.
(passez la souris sur l’image pour un fallback)

Il existe une autre méthode, plus souple à utiliser, mais qui requiert un sprite différent.

Plutôt que de spécifier une zone à afficher, nous allons indiquer un élément du SVG. Par défaut, nous allons cacher toutes les images et n’afficher que celle qui correspond au fragment en cours, grâce à du CSS embarqué dans notre SVG :

<svg …>
	<style>…</style>
	<g id="color">…</g>
	<g id="gray">…</g>
Chaque image est regroupée dans un groupe ayant un identifiant
svg > g        { display: none; }
svg > g:target { display: block; }
En CSS, on cache tous les groupes sauf le target

Ensuite, pour s’en servir :

Sans fragment le sprite n’affiche rien
octocat.svg#gray
(passez la souris sur l’image pour un fallback)
octocat.svg#color
(passez la souris sur l’image pour un fallback)

Si vous souhaitez utiliser cette méthode il faudra revoir votre façon de concevoir vos sprites. Cette fois, toutes les images seront placées les unes par dessus les autres. Cela veut également dire que votre viewBox doit être fixe et que chaque image doit avoir la même taille.

Droits sur ce billet

Ce billet est sous contrat Creative Commons. Vous êtes libre de :

Selon ces conditions :

  • Vous devez citer mon nom, mais pas d'une manière qui suggérerait que je vous soutienne ou approuve l'utilisation que vous en faites. (Parternité)
  • Vous n'avez pas le droit de l'utiliser à des fins commerciales. (Pas d'utilisation commerciale)
  • Si vous le modifiez, transformez ou l'adaptez, vous n'avez le droit de distribuer le résultat que sous un contrat identique à celui-ci. (Partage des conditions initiales à l'identique)

Commentaires

Aucun commentaire pour le moment.

Laissez le vôtre !

Les commentaires pour ce billet sont fermés.

À propos du billet

samedi 23 mars 2013 à 12:26

Classé dans :

aucun commentaire

Navigation inter-billets