SVG, style et animation avec CSS

Les articles de Sara Soueidan sont devenus une référence incontournable en matière de SVG. Sara passe ici en revue les étapes de l'application de styles et d'animation CSS aux SVG.

Par

On peut utiliser CSS pour animer les SVG et leur appliquer un style, tout comme on le fait pour les éléments HTML. Dans cet article qui reprend une conférence que j’ai donnée à CSSconfEU et à From the Front, je vais passer en revue les techniques qui permettent de le faire.

Je vous montrerai aussi comment exporter et optimiser les SVG, les techniques permettant de les intégrer et la façon dont chacune affecte les styles et les animations qui leur sont appliqués, puis nous passerons au style et à l’animation avec CSS.

Introduction

SVG est un format d’image vectorielle de type XML pour les graphiques en 2D, qui permet l’interactivité et l’animation. Pour le dire autrement, les SVG sont des balises XML avec lesquelles il est possible de créer des formes et des graphiques que vous pouvez animer comme les éléments HTML.

Les animations et l’interactivité peuvent être ajoutées via CSS ou JavaScript. Dans cet article, nous nous concentrerons sur CSS.

Les raisons pour lesquelles vous devriez utiliser SVG sont nombreuses :

  • Les graphiques SVG sont extensibles et indépendants de la résolution. Leur rendu est impeccable sur tous supports, des écrans retina jusqu’aux supports imprimés.
  • La compatibilité navigateurs est excellente. Les solutions de rechange (fallbacks) pour les navigateurs incompatibles sont simples, comme nous le verrons dans cet article.
  • Étant de nature “textuelle”, ils peuvent être Gzippés, et sont beaucoup plus légers que leurs équivalents bitmap (JPEG et PNG).
  • Les SVG sont interactifs et on peut leur appliquer un style via CSS et JavaScript.
  • SVG comprend des effets graphiques, tels que les opérations de détourage (clipping) et de masquage (masking), les background blend modes et les filtres, comme si vous aviez les possibilités d’édition de Photoshop à l’intérieur de votre navigateur.
  • Les SVG sont accessibles, ce qui leur donne un avantage sur HTML5 Canvas dont le contenu n’est pas accessible. De plus, vous pouvez inspecter chaque élément de SVG dans votre DevTool préféré comme vous le feriez pour un élément HTML. Enfin, les SVG sont accessibles aux lecteurs d’écrans si vous faites en sorte que ce soit possible. Nous reviendrons sur la question de l’accessibilité dans la dernière partie de cet article.
  • Il existe de nombreux outils vous permettant de créer, de modifier et d’optimiser les SVG, et d’autres outils qui facilitent votre travail sur SVG et vous feront gagner beaucoup de temps.

Exportation de SVG depuis un éditeur graphique et optimisation

Les trois éditeurs graphiques les plus populaires sont :

Adobe Illustrator est une application payante d’Adobe. C’est un éditeur très utilisé, avec une belle interface utilisateur et de nombreuses fonctionnalités qui en font l’outil préféré des designers.

Inkscape est une alternative gratuite. Même si son interface n’est pas aussi bien faite que celle d’Illustrator, il a tout ce qu’il faut pour travailler avec les graphiques vectoriels.

Sketch est une application pour Mac. Elle n’est pas gratuite mais elle rencontre un gros succès auprès des designers depuis peu et elle gagne rapidement en popularité, offrant de nombreuses ressources et outils créés récemment pour améliorer votre travail.

Choisissez celui qui vous convient pour créer vos SVG. Avant d’intégrer vos SVG dans une page web, il vous faudra les exporter depuis votre éditeur et les nettoyer un peu pour pouvoir travailler avec.

Je me réfèrerai ici à Illustrator, mais les manips sont valables pour tous les éditeurs, à l’exception des options spécifiques à Illustrator que nous allons voir maintenant.

Pour exporter un SVG depuis Illustrator, allez sur File / Save as puis choisissez l’extension .svg depuis le menu déroulant. Un panneau apparaît contenant un ensemble d’options d’exportation de SVG (illustration ci-dessous).


image
(Voir une version élargie)

L’article de Michaël Chaize Export SVG for the Web With Illustrator CC explique pourquoi les options choisies ci-dessus sont les meilleures.

NdT : vous pouvez aussi vous référer à l’excellente introduction à SVG de Chris Coyier traduite ici même. Pour l’exportation depuis Sketch, vous pouvez consulter cet article de Tuts+.

Quel que soit votre éditeur graphique, il ne retournera pas un SVG parfaitement propre et optimisé. Les fichiers SVG exportés contiennent des informations redondantes, telles que des métadonnées de l’éditeur, des commentaires, des groupes vides, des valeurs par défaut, des valeurs non optimales et bien d’autres choses qui peuvent être supprimées ou converties sans affecter le rendu du SVG. Si vous utilisez un SVG que vous n’avez pas créé vous-même, le code n’est certainement pas optimal et il est conseillé d’utiliser un outil d’optimisation.

Il n’en manque pas. SVG Editor de Peter Collingridge est un outil en ligne dans lequel vous entrez votre code SVG, soit directement soit en faisant un upload du fichier. L’outil vous propose plusieurs options d’optimisation, y compris le nombre de décimales (decimal places) pour les points de coordonnées :


image
(Voir une version élargie)

Lorsque vous cochez une option d’optimisation, vous voyez immédiatement le résultat que cela donnera, ce qui vous aide à choisir les bonnes options. Certaines pourraient abîmer votre SVG. A priori, une décimale devrait pouvoir être suffisant, si vous travaillez sur un fichier SVG comportant de nombreux chemins, le simple fait de passer de quatre à une décimale peut diminuer par deux le poids de votre fichier. Cependant, il pourrait aussi abîmer le SVG, c’est pourquoi la possibilité de visualiser le résultat est vraiment intéressante.

Si vous préférez un outil offline, essayez SVGO (SVG Optimizer) et son interface Glisser/Déplacer. C’est une bonne alternative.

La capture d’écran qui suit (correspondant au chemin visualisé dans l’image précédente) est une illustration simple de l’avant et de l’après optimisation :


image

Remarquez la taille du SVG d’origine comparée à celle de la version optimisée, et notez l’amélioration de la lisibilité.

Une fois optimisé, votre SVG est prêt à être intégré à la page web et personnalisé ou animé avec CSS.

Appliquer un style avec CSS

Entre HTML et CSS, la ligne de partage est claire : HTML pour le contenu et la structure, CSS pour l’apparence. SVG brouille un peu cette distinction. SVG 1.1 n’avait pas besoin de CSS pour appliquer les styles, il utilisait ce qu’on applelait des “attributs de présentation”.

L'expression attributs de présentation est un raccourci pour dire qu’on donne des propriétés CSS à un élément, comme des propriétés spéciales de style. Elles peuvent même contribuer à la cascade de styles, mais nous y reviendrons.

L’exemple suivant montre un code SVG qui utilise les attributs de présentation pour styliser les “bordures” (stroke) et le background color (fill) d’un polygone en forme d’étoile :

//HTML
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="300px" viewBox="0 0 300 300">
  <polygon
fill = "#FF931E"
stroke = "#ED1C24"
stroke-width = "5"
points = "279.1,160.8 195.2,193.3 174.4,280.8   117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 "/>
</svg>

Les attributs fill, stroke et stroke-width sont des attributs de présentation.

En SVG, certaines propriétés CSS peuvent être définies à l’aide d’attributs SVG et vice versa. La spécification SVG liste les attributs SVG qui peuvent être définis comme des propriétés CSS. Certains attributs sont partagés avec CSS, comme opacity et transform, d’autres non, comme fill, stroke et stroke-width parmi d’autres.

Avec SVG 2, cette liste inclut x, y, width, height, cx, cy et quelques autres attributs de présentation qu’il n’était pas possible de donner via CSS dans SVG 1.1. La nouvelle liste d’attributs peut être consultée dans la spécification SVG 2.

Une autre façon d’appliquer des styles à un SVG est d’utiliser les propriétés CSS. Comme avec HTML, on peut les appliquer via des attributs en ligne :

//HTML
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" style="width: 300px; height: 300px;" viewBox="0 0 300 300">
<polygon
  style = "fill: #FF931E; stroke: #ED1C24; stroke-width: 5;"
  points = "279.1,160.8 195.2,193.3 174.4,280.8   117.6,211.1 27.9,218.3 76.7,142.7 42.1,59.6 129.1,82.7 197.4,24.1 202.3,114 "/>
</svg>

On peut aussi les fixer dans les ensembles de règles à l’intérieur d’une balise <style>. La balise <style> peut être placée à l’intérieur d’une balise <svg> :

//HTML
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="300px" height="300px" viewBox="0 0 300 300">
  <style type="text/css">
  <![CDATA[
  selector {/* styles */}
  ]]>
  </style>
  <g id=".."> … </g>
</svg>

Et elle peut être placée en dehors si vous intégrez le SVG en ligne dans le document :

<!DOCTYPE html><!-- document HTML5 -->
<html>
<head> … </head>
<body>
<style type="text/css">
  /* les règles de style */
</style>
<!-- l&rsquo;espace de nom xml (xmlns) est optionnel dans un document HTML5 -->
<svg viewBox="0 0 300 300">
<!-- le contenu SVG -->
</svg>
</body>
</html>

Et si vous voulez complètement séparer style et balisage, vous pouvez lier votre SVG à une feuille de style externe via la balise <?xml-stylesheet> comme ci-dessous :

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/css" href="style.css"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width=".." height=".." viewBox="..">
  <!-- SVG content -->
</svg>

Cascade de styles

Nous avons dit tout à l’heure que les attributs de présentation sont une espèce particulière de propriétés de styles, et qu’ils sont un raccourci pour appliquer une propriété CSS sur un noeud SVG. Il est donc logique que les attributs de présentation SVG contribuent à la cascade CSS.

En fait, les attributs de présentation sont considérés comme des contributeurs de niveau inférieur et sont écrasés par toutes les autres définitions de style : feuilles de style externes, style en ligne,... comme le montre ce diagramme de l’ordre des styles dans la cascade CSS, du plus faible (en haut) au plus fort (en bas).


image

Par exemple, dans le code suivant nous avons dessiné un élément SVG circulaire. La couleur de remplissage du cercle sera violet foncé (deepPink) qui prend la précédence sur la couleur de remplissage définie dans l’attribut de présentation (blue).

<circle cx="100" cy="100" r="75" fill="blue" style="fill:deepPink;" />

Sélecteurs

La plupart des sélecteurs CSS peuvent être utilisés pour sélectionner des éléments SVG. En plus du type général, sélecteurs de classes et ID, les SVG peuvent être stylés avec les pseudo-classes dynamiques de CSS2 (:hover, :active et :focus) et les pseudo-classes (:first-child, :visited, :link et :lang). Les autres pseudo-classes CSS2, dont celles qui touchent au contenu généré (comme ::before et ::after) ne font pas partie de la définition du langage SVG et du coup n’ont pas d’effet sur le style des SVG.

Voici une animation simple de la couleur de remplissage d’un cercle depuis le violet profond jusqu’au vert, lorsqu’on le survole :

<style>
circle {
  fill: deepPink;
  transition: fill .3s ease-out;
}

circle:hover {
  fill: #009966;
}
</style>

On peut créer des effets bien plus impressionnants. Un effet simple mais très joli, tiré de la collection d’icône d’Iconic, consiste à allumer une ampoule lorsqu’on la survole (voir la démo).

Notes

Les attributs de présentation étant exprimés comme des attributs XML, ils sont sensibles aux majuscules & minuscules, de même que les mots-clés qu’ils utilisent. Par exemple il faut écrire fill et non pas Fill, et font-style="italic" sans majuscules.

Tous les autres styles spécifiés comme règles CSS — que ce soit dans un attribut de style ou une balise <style> ou dans une feuille de style externe — sont soumis aux règles grammaticales définies dans les spécifications CSS, qui sont en général moins sensibles au problèmes des majuscules et des minuscules. Ceci étant, la spécification SVG Styling recommande d’utiliser les mêmes noms de propriétés que celles qui sont définies dans les spécifications CSS.

Animer les SVG avec CSS

Les SVG peuvent être animés de la même façon que les éléments HTML, en utilisant les keyframes CSS et les propriétés d’animation, ou avec des transitions CSS.

Dans la plupart des cas, les animations complexes comportent des transformations — une translation, une rotation, un redimensionnement ou une déformation.

Les éléments SVG répondent aux transform et transform-origin de la même façon que les éléments HTML, cependant certaines différences résultent du fait que contrairement à ceux-ci, les éléments SVG ne sont pas régis par le modèle de boîte et par conséquent n’ont ni marge, ni bordure, ni padding.

Par défaut, le point d’origine de la transformation d’un élément HTML est fixé à (50%, 50%), c’est à dire au centre de l’élément. Avec SVG par contre, ce point est positionné à l’origine du système de coordonnées actuel de l’utilisateur, c’est à dire au point (0,0) en haut à gauche du canevas. ( NdT : sur les systèmes de coordonnées, vous pouvez vous référer à la belle série d’articles (en anglais) de Sara Soueidan Understanding SVG Coordinate Systems & Transformations.)

Supposons que nous ayons une <div> HTML et un élément SVG <rect> :

<!DOCTYPE html>
…
<div style="width: 100px; height: 100px; background-color: orange"> </div>
<svg style="width: 150px; height: 150px; background-color: #eee">
  <rect width="100" height="100" x="25" y="25" fill="orange" />
</svg>

Si nous voulions faire pivoter les deux éléments de 45 degrés, sans modifier le point d’origine par défaut de la transformation, nous obtiendrions le résultat suivant (le cercle rouge indique la position du point d’origine de la transformation) :


image
(Voir une version élargie)

Mais quid si nous voulions faire pivoter l’élément SVG autour de son centre plutôt qu’à partir du coin supérieur gauche du canevas ? Il nous faut ici indiquer de manière explicite le point d’origine, à l’aide de la propriété transform-origin.

On peut pour cela utiliser des valeurs absolues (par exemple en pixels) ou des pourcentages. Dans ce dernier cas, la valeur sera relative à la boîte de l’élément, y compris le trait utilisé pour dessiner sa bordure. Si vous spécifiez le point d’origine en valeurs absolues, il sera relatif au système de coordonnées actuel du canevas SVG de l’utilisateur.

En reprenant notre exemple précédent, si nous voulions fixer le point d’origine de la tranformation au centre, en utilisant des pourcentages, nous écririons :

<!DOCTYPE html>
<style>
  div, rect {
  transform-origin: 50% 50%;
}
</style>

Et la transformation ressemblerait à ceci :


image
(Voir une version élargie)

Ceci dit, à l’heure actuelle les pourcentages ne fonctionnent pas avec Firefox. C’est un bug connu. Donc, en attendant, il vaut mieux utiliser les valeurs absolues, ce qui ne vous empêche pas d’utiliser les valeurs en pourcentage pour les navigateurs WebKit.

Dans l’exemple qui suit, nous faisons tourner un moulinet sur un axe au moyen d’une animation CSS. Pour le faire tourner sur son point central, nous fixons l’origine de la transformation en pixels et en pourcentage :

<svg>
<style>
.wheel {
  transform-origin: 193px 164px;
  -webkit-transform-origin: 50% 50%;
  -webkit-animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
  animation: rotate 4s cubic-bezier(.49,.05,.32,1.04) infinite alternate;
}

@-webkit-keyframes rotate {
  50% {
    -webkit-transform: rotate(360deg);
  }
}

@keyframes rotate {
  50% {
    transform: rotate(360deg);
  }
}

</style>
<!-- SVG content -->
</svg>

Voici le résultat sur CodePen.

Open this live demo on CodePen.

Remarquez bien qu’à l’heure actuelle, les transformations CSS 3D ne sont pas optimisées lorsqu’elles s’appliquent à des éléments SVG. Elles ont le même niveau de performance que les attributs transform de SVG. Cependant, Firefox optimise les SVG dans une certaine mesure.

Animer les chemins SVG

On ne peut pas animer un chemin SVG d’une forme vers une autre en CSS. Si vous voulez morpher les chemins — c’est à dire animer d’un chemin vers un autre — alors il vous faudra utiliser JavaScript pour l’instant. Si vous le faites, je vous recommande d’utiliser Snap.svg de Dmitry Baranovsky, qui est aussi à l’origine de la bibliothèque SVG Raphaël.

On dit souvent que Snap.svg est à SVG ce que jQuery est à HTML, et il rend la vie avec SVG plus facile.

Ceci dit, vous pourriez créer et animer des effets de dessin d’une ligne avec CSS. L’animation vous demanderait de connaître la longueur totale du chemin que vous animez et d’utiliser les propriétés stroke-dashoffset et stroke-dasharray ( NdT : Chris Coyier a écrit un super article à ce sujet, Ligne animée en SVG, traduit ici-même). Une fois connue la longueur du chemin, vous pouvez l’animer avec les règles CSS suivantes :

#path {
stroke-dasharray: pathLength;
stroke-dashoffset: pathLength;
/* transition stroke-dashoffset */
transition: stroke-dashoffset 2s linear;
}

svg:hover #path{
  stroke-dashoffset: 0;
}

Dans l’exemple ci-dessus, le chemin est dessiné sur une durée de deux secondes lorsqu’on survole le SVG.

Dans la démo suivante, nous utilisons la même technique puis une transition CSS, avec un délai, pour allumer l’ampoule une fois l’animation du chemin parvenue à son terme.

#cable {
  stroke: #FFF2B1;
  stroke-dasharray: 4000 4000;  
  stroke-dashoffset: 4000;
  stroke-width: 4;
  transition: stroke-dashoffset 8s linear;
}

svg:hover #cable {
  stroke-dashoffset: 0;
}

/* allumer la lampe */
.inner-lamp{
  fill:grey;
  transition: fill .5s ease-in 6s;
}

svg:hover .inner-lamp {
  fill: #FBFFF8;
}
/* … */

Vous pouvez voir la démo live sur JS Bin. Remarquez que vous pourriez aussi écrire stroke-dasharray: 4000; à la place de stroke-dasharray: 4000 4000 — si les deux valeurs de ligne et d’intervalle sont égales, une seule valeur peut s’appliquer aux deux.

Cependant, il peut arriver que vous ne connaissiez pas la longueur exacte du chemin à animer. Dans ce cas, vous pouvez utiliser JavaScript pour extraire cette longueur à l’aide de la méthode getTotalLength() :

var path = document.querySelector(&rsquo;.drawing-path&rsquo;);
path.getTotalLength();
//set CSS properties up
path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;
//set transition up
path.style.transition = &rsquo;stroke-dashoffset 2s ease-in-out&rsquo;;
// animate
path.style.strokeDashoffset = &rsquo;0&rsquo;;

Le petit code ci-dessus est un exemple très simple montrant qu’on peut obtenir la même chose avec JavaScript.

Jake Archibald a écrit un excellent article expliquant cette méthode en détail, avec une belle démo interactive pour comprendre exactement ce qui se passe et comment les deux propriétés SVG permettent d’obtenir l’effet désiré. Je vous recommande la lecture de cet article si vous souhaitez en savoir plus sur cette technique.

Intégrer les SVG

Un SVG peut être intégré dans un document de six manières différentes, chacune avec ses avantages et ses inconvénients ( NdT : ce sujet est bien décrit dans l’article déjà cité de Chris Coyier Utiliser SVG).

La façon dont vous intègrerez votre SVG aura un impact sur la possibilité, ou non, d’utiliser CSS pour les animations et interactions.

Vous pouvez intégrer un SVG ainsi :

  1. comme une image, à l’aide de la balise <img> :

    <img src="mySVG.svg" alt="" />
    
  2. comme une image de background en CSS :

    .el {background-image: url(mySVG.svg);}
    
  3. Comme un objet, à l’aide de la balise <object> :

    <object type="image/svg+xml" data="mySVG.svg"><!-- fallback ici --></object>
    
  4. comme une iframe, à l’aide de la balise <iframe> :

    <iframe src="mySVG.svg"><!-- fallback here →</iframe>
    
  5. à l’aide de la balise <embed> :

    <embed type="image/svg+xml" src="mySVG.svg" />
    
  6. en ligne, avec la balise <svg> :

    <svg version="1.1" xmlns="http://www.w3.org/2000/svg" …>
    <!-- contenu svg ici -->
    </svg>
    

La balise <object> est la façon basique d’intégrer un fichier SVG, son principal avantage est qu’elle comporte un mécanisme standard pour fournir une image, ou un texte, au cas où le rendu du SVG est impossible. Si le SVG ne peut pas être affiché, par exemple si son URI est erronée, le navigateur affichera le contenu situé entre les balises <object>.

<object type="image/svg+xml" data="mySVG.svg">
  <img src="fallback-image.png" alt="…" />
</object>

La balise <embed> n’a jamais fait partie d’aucune spécification HTML et pourtant elle est encore largement supportée. Elle sert à inclure du contenu nécessitant un plugin externe pour pouvoir fonctionner. Le plugin Adobe Flash requiert la balise <embed> et c’est à peu près la seule raison de son utilisation avec SVG. <embed> ne fournit pas de mécanisme de fallback.

On peut aussi intégrer SVG en ligne, comme un “îlot de code isolé”, à l’aide de la balise <svg>. C’est une des façons les plus courantes d’intégrer SVG aujourd’hui. Il est beaucoup plus facile de travailler avec un SVG en ligne et CSS parce que le SVG peut être stylisé et animé au moyen de règles de style qu’on peut placer où l’on veut dans le document. Autrement dit, les styles n’ont pas besoin d’être placés entre les balises <svg> pour fonctionner — alors que c’est le cas pour les autres techniques.

Intégrer le SVG en ligne est un bon choix, si vous acceptez d’alourdir votre page et que vous renoncez aux mécanismes de fallback. Remarquez également que le SVG en ligne ne peut pas être mis en mémoire cache.

Le SVG intégré via une balise <img> ou comme background image sont traités de la même manière, pour ce qui est du style et de l’animation. Les styles et animations appliqués sur un SVG via une ressource CSS externe ne seront pas préservés une fois le SVG intégré.

La table qui suit montre dans quelle mesure les animations et interactions CSS sont préservées lorsqu’un SVG est intégré à l’aide de chacune des six techniques et les compare aux animations SMIL de SVG (traduction de l’article à paraître bientôt sur La Cascade). La dernière colonne montre que dans tous les cas les animations SVG (SMIL) sont préservées.


image
Tableau montrant la préservation, ou non, des styles, animations et interactions CSS selon la technique d’intégration utilisée pour SVG

Le comportement indiqué dans le tableau est le comportement standard. Cependant, les implémentations peuvent varier selon les navigateurs et des bugs peuvent exister.

Remarquez également que même si les animations SMIL sont préservées, les interactions SMIL ne fonctionneront pas avec un SVG intégré comme image (c’est à dire <img> ou via CSS).

Rendre SVG responsif

Une fois votre SVG embarqué, il faut vous assurer qu’il est responsif.

Selon la technique d’intégration choisie, il vous faudra peut-être appliquer certaines corrections pour qu’il soit responsif sur tous les navigateurs. La façon dont les navigateurs déterminent les dimensions du SVG diffèrent selon la technique d’intégration et l’implémentation de SVG diffère selon les navigateurs.

Je ne vais pas entrer dans les détails des différences entre navigateurs mais simplement vous donner les manières de corriger les problèmes. Pour une analyse en détail vous pouvez consulter mon article sur Codrops.

Quelle que soit la technique choisie, la première chose à faire est de supprimer les attributs width et height de la racine de l’élément svg.

Il vous faut préserver l’attribut viewBox et régler l’attribut preserveAspectRatio sur xMidYMid meet — si ce n’est pas déjà le cas. Remarquez que vous n’êtes pas obligé de le faire car c’est la valeur par défaut si vous ne la modifiez pas.

Quand un SVG est intégré via CSS comme image de background, on n’a pas besoin de recourir à ces corrections. Il se comportera comme n’importe quelle image bitmap de background et répondra comme il faut aux propriétés CSS de background-image.

Un SVG intégré via une balise <img> prendra automatiquement la largeur du contenant dans tous les navigateurs (une fois la lageur supprimée de <svg> bien sûr). Il se redimensionnera comme il faut et sera fluide dans tous les navigateurs à l’exception d’Internet Explorer. IE fixe la hauteur du SVG à 150 pixels, ce qui l’empêche de se redimensionner correctement. Pour corriger cela, il faut régler explicitement la largeur à 100% sur <img>.

<img src="mySVG.svg" alt="SVG Description." />
img {
  width: 100%;
}

Même chose pour un SVG intégré via une balise <object>. Pour la même raison, il faut régler la largeur de l’<object> à 100%.

object {
  width: 100%;
}

Même si <iframe> est très proche d’<object>, les navigateurs semblent le traiter différemment. Tous les navigateurs lui donnent par défaut la taille des éléments remplacés en CSS, qui est de 300 par 150 pixels.

La seule façon de rendre un iframe responsif tout en conservant son ratio d’aspect est d’utiliser le hack du padding imaginé par Thierry Koblenz dans A List Apart. L’idée de ce hack est d’utiliser la relation entre le padding d’un élément et sa largeur, afin de créer un élément ayant un ratio intrinsèque entre sa hauteur et sa largeur.

Quand le padding d’un élément est fixé en pourcentage, le pourcentage est calculé relativement à la largeur de l’élément, même lorsqu’il s’agit du padding supérieur ou inférieur de l’élément.

Pour appliquer ce hack et rendre le SVG responsif, le SVG doit être enveloppé dans un conteneur, puis on applique un style au conteneur et au SVG (c’est à dire à l’iframe) comme suit :

<!-- envelopper le svg dans un conteneur -->
<div class="container">
  <iframe src="my_SVG_file.svg">
    <!-- fallback ici -->
  </iframe>
</div>

.container {
  /* réduire à zéro la hauteur du conteneur */
  height: 0;        

  /* spécifier la largeur voulue (une valeur en %) */     
  width: width-value;    

  /* appliquer padding comme suit */
  /* cette formule garantit que le ratio d'aspect du conteneur est égal à celui du SVG */
  padding-top: (svg-height / svg-width) * width-value;
  position: relative;    /* crée un contexte de positionnement pour le SVG */
}

Les variables svg-height et svg-width sont les valeurs de la hauteur et de la largeur du <svg>, les dimensions que nous avons supprimées précédemment. Et la width-value est la largeur que vous souhaitez donner au conteneur du SVG sur la page.

Enfin, le SVG lui-même (l’iframe) doit être positionné de manière absolue à l’intérieur du conteneur :

iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Nous positionnons l’iframe de manière absolue car la réduction à zéro de la hauteur du conteneur suivie de l’application du padding repousseraient l’iframe en-dehors des limites du conteneur. Donc, pour le “faire revenir”, nous le positionnons absolument. Vous pouvez lire davantage sur ce sujet dans mon article sur Codrops.

Finalement, un SVG intégré en ligne dans une balise <svg> devient responsif lorsque les hauteur et largeur sont supprimées car les navigateurs partent d’une largeur de 100% et redimensionneront le SVG en fonction. Toutefois, IE présente le même problème de hauteur fixe à 150 pixels que pour <img> et malheureusement cette fois-ci il ne suffit pas de fixer la largeur à 100%.

Pour rendre fluide dans IE un SVG en ligne, nous devons là aussi appliquer le hack du padding. Donc nous enveloppons <svg> dans un conteneur, nous appliquons les règles mentionnées précédemment et positionnons absolument le <svg>. La seule différence est que nous n’avons pas besoin de fixer explicitement la hauteur et la largeur de <svg> après l’avoir positionné.

svg {
  position: absolute;
  top: 0;
  left: 0;
}

Utiliser les media queries CSS

SVG accepte les media queries CSS. Vous pouvez utiliser les media queries pour modifier le style d’un SVG à différentes tailles de viewport.

Cependant, un point important à noter ici est que le viewport auquel se réfère SVG est le viewport du SVG lui-même, pas le viewport de la page !

Dans le concept, c’est assez similaire aux element queries.

Un SVG intégré avec <img>, <object> ou <iframe> correspond au viewport établi par ces éléments. C’est à dire que les dimensions de ces éléments forment le viewport à l’intérieur duquel le SVG doit être dessiné et, de là, forment le viewport auquel les conditions des media queries CSS seront appliquées.

L’exemple suivant inclut un ensemble de media queries à l’intérieur d’un SVG qui est ensuite référencé à l’aide d’une balise <img> :

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 194 186">
  <style>
    @media all and (max-width: 50em) {
      /* sélectionnez les éléments SVG et appliquez un style */
    } 
    @media all and (max-width: 30em) {
      /* styles  */
    }
  </style>
  <!-- éléments SVG ici -->
</svg>

Quand le SVG est référencé, il prend les styles spécifiés dans les media queries ci-dessus lorsque <img> a une max-width de 50em ou 30em respectivement.

<img src="my-logo.svg" alt="Page Logo." />

Vous pouvez en apprendre plus sur les media queries à l’intérieur de SVG dans l’article d’Andreas Boven pour Dev.Opera.

Conclusion

Les SVG sont des images, et comme les images ils peuvent être accessibles. Il est important de rendre également vos SVG accessibles.

Je ne peux pas insister plus que cela : Rendez vos SVG accessibles. On peut faire beaucoup de choses pour cela. L’article de Leonie Watson, sur Sitepoint est un guide excellent et complet. Parmi ses conseils, l’utilisation des balises <title> et <desc> dans le <svg>, l’utilisation d’attributs ARIA et bien d’autres choses.

N’oubliez pas non plus d’optimiser vos SVG et de prévoir des solutions de rechange pour les incompatibilités navigateurs. Je vous recommande la présentation de Todd Parker.

Last but not least, vérifiez régulièrement les questions de compatibilité sur Can I Use. J’espère que vous avez trouvé cet article utile, merci de l’avoir lu !


Ressources complémentaires en français :

Utiliser SVG, par Chris Coyier
Animer un SVG avec CSS, par Chris Coyier
Une ligne animée avec SVG, par Chris Coyier
Les dégradés SVG, par Joni Trythall
Animer un dégradé SVG, par Joni Trythall
SVG Ground, tout, absolument tout sur SVG !

Ressources complémentaires en anglais :

A compendium of SVG information, par Chris Coyier : une avalanche d'infos, d'articles, de ressources sur SVG. Vous ne pourrez plus dire que vous ne saviez pas !
Une plateforme sur SVG, dans "showcase" vous trouverez des motifs à télécharger.
Snap.svg une bibliothèque JavaScript par Dmitry Baranovskiy.
Démos SVG sur Codrops.
Démos SVG sur CodePen.
SVG editor, de Peter Collingridge, bon outil pour éditer vos svg, beaucoup d'options d'optimisation pour alléger les fichiers.

Et enfin, 3 vidéos géniales de Kyle Foster,
An Optimized Workflow
SVG Optimization, End-all Be-all Edition
Manipulating SVG with CSS


Intéressé par SVG ? Sur la Cascade, retrouvez des articles et ressources.


original paru le dans Smashing Magazine.

Sur l’auteur : est une intégratrice web libanaise. Elle aime enseigner et écrit des tutoriels sur son blog et sur Codrops, dont elle est un des membres actifs. Vous pouvez la suivre sur Twitter et sur Github.

Traduit avec l’aimable autorisation de Smashing Magazine et de l’auteur.
Copyright Smashing Magazine © 2014.