SVG : Scalable Vector Graphics dans une page HTML
LE code des images SVG (Scalable Vector Graphics) est interprété par les navigateurs WEB et peut donc être intégré dans une page HTML. L syntaxe est par contre celle de XML, plus stricte que le HTML. Cette page donne le minimum à connaître pour écrire des images SVG sans passer par un éditeur de telles images.
Une connaissance minimale du HTML est préférable, voyez cette page. La syntaxe du XML, dans laquelle est écrite une image SVG, est plus susceptible que celle du HTML. Par exemple, toute balise ouverte doit être fermée, par exemple toute la description doit se faire entre les balises <svg> et </svg>. Les balises qui ne sont pas englobantes peuvent être auto-fermées par une barre, comme par exemple <line x1="8" y1="5" x2="59" y2="19" />
Page commencée le 2025.01.18 ; elle est testée avec FireFox 128.6.0esr et Chromium 132.0.6834.83 sur GNU/Linux Debian 12 Bookworm (64 bits)
1. Généralités
1.1 Utilisez les styles 2. Éléments simples |
3. Éléments complexes
3.1 Polygones 4. Textes5. Image6. Liens |
7. Attributs graphiques |
1. Généralités
Typiquement, un graphique SVG défini de la sorte produira un rectangle :
<svg width="200" height="100" style="border:1px grey solid" xmlns="http://www.w3.org/2000/svg"> <rect x="75" y="20" width="80" height="40" stroke="cyan" stroke-width="3" fill="yellow" /> </svg>
- La première ligne réserve un espace de 200 pixels de large et de 100 de haut, avec un bord gris d’un pixel d’épaisseur
- La deuxième ligne dessine un rectangle dont le coin supérieur gauche est situé à 75 pixels du bord gauche et à 20 pixels du haut, et de dimension de 80×40 pixels. Il sera jaune, le bord de 3 pixels de large étant cyan
1.1 Utilisez les styles
La bonne intégration du SVG dans le HTML permet que des attributs contenus dans la balise puissent être regroupés dans un attribut style="" :
<rect x="75" y="20" width="80" height="40" style="stroke:cyan; stroke-width:3; fill:yellow" />
…ou encore faire l’objet d’une classe définie entre les balises <style> et </style> de début de page HTML.
<html><head> <style> .ua { stroke:cyan; stroke-width:3; fill:yellow; } </style> </head><body> <svg width="300" height="200" xmlns="http://www.w3.org/2000/svg"> <rect class="ua" x="75" y="20" width="80" height="40" /> </svg> </body></html>
<g> permet de grouper des éléments pour leur appliquer les mêmes attributs :
<svg width="90" height="65" xmlns="http://www.w3.org/2000/svg" style="border:1px solid #777"> <g fill="cyan" stroke="blue" stroke-width="6"> <rect x="10" y="10" width="70" height="30" /> <circle cx="55" cy="40" r="15" /> </g> </svg>
Les attributs graphiques sont explicités au chapitre 7. Attributs graphiques.
1.2 L’importance de l’attribut viewbox
Les attributs des balises SVG contiennent souvent des nombres, qui représentent a priori les coordonnées en pixels. Voici un exemple :
<svg width="200" height="100" style="border:1px solid #777"> <rect x="10" y="10" width="40" height="20"> </svg>
Mais comme les graphiques doivent pouvoir s’afficher à n’importe quelle échelle («scalable»), il existe un attribut permettant d’agrandir ou diminuer le contenu d’un graphique SVG. viewbox="0 0 400 200" oblige SVG à considérer l’espace réservé de 200×100 comme deux fois plus grand. L’affichage de ses éléments est de ce fait diminué de moitié :
<svg width="200" height="100" viewbox="0 0 400 200" style="border:1px solid #777"> <rect x="10" y="10" width="40" height="20"> </svg>
Avec viewbox="0 0 100 50", l’espace réservé par SVG sera considéré comme diminué de moitié et les dimensions du rectangles seront doublées :
<svg width="200" height="100" viewbox="0 0 100 50" style="border:1px solid #777"> <rect x="10" y="10" width="40" height="20"> </svg>
Ci-dessous, viewbox="10 5 200 100" conserve les proportions du rectangle mais supprime les marges de gauche de 10 pixels et de droite de 5 premiers pixels :
<svg width="200" height="100" viewbox="10 5 200 100" style="border:1px solid #777"> <rect x="10" y="10" width="40" height="20"> </svg>
viewbox="8 3 100 50" supprime 8 pixels de la marge de gauche et 3 de la marge du haut du rectangle puis double les proportions du rectangle, en ce compris les marges résiduelles, à savoir respectivmement (10 -8) *2 =4 et (10 -3) *2 =14 :
<svg width="200" height="100" viewbox="8 3 100 50" style="border:1px solid #777"> <rect x="10" y="10" width="40" height="20"> </svg>
Note : Si les dimensions de l’image ne sont pas proportionnelles à celles de viewbox,
- c’est le rapport le plus modéré qui l’emporte pour les dimensions du l’élément, sauf en présence de l’attribut preserveAspectRatio="none" de la balise <svg> qui étire indépendamment les largeur et hauteur des éléments
- les marges résiduelles seront indépendamment proportionnelles, selon des modalités qui me semblent complexes, qu’il me reste à déterminer.
<svg width="200" height="100" viewbox="8 3 100 20" style="border:1px solid #777"> <rect x="10" y="10" width="40" height="20"> </svg>
2. Éléments simples
2.1 Rectangle
En dehors des éléments vus plus haut, il est possible d’arrondir les angles d’un rectangle :
- rx= permet de définir le rayon de courbure de l’axe des x (0 par défaut)
- ry= permet de définir le rayon de courbure de l’axe des y (idem)
<svg width="150" height="100" style="border:1px grey solid" xmlns="http://www.w3.org/2000/svg"> <rect x="15" y="10" width="120" height="80" rx="30" ry="15" /> </svg>
2.2 Cercles
Les cercles sont définis par :
- cx="" pour l’abscisse du centre
- cy="" pour l’ordonnée du centre
- r="" pour le rayon
<svg width="100px" height="100px"> <circle cx="50" cy="50" r="44" stroke="#b07" stroke-width="5px" fill="#ff7" /> </svg>
2.3 Ellipse
Les ellipses sont définies comme les cercles, mais avec deux rayons, rx et ry
<svg width="100px" height="100px"> <ellipse cx="50" cy="50" rx="30" ry="44" stroke="#70b" stroke-width="5px" fill="7ff" /> </svg>
2.4 Lignes
Une ligne simple est définie par les coordonnées de deux points, x1, y1 et x2, y2. Cet élément est sensible aux attributs de couleur et de trait.
<svg width="120px" height="120px" style="border:1px grey solid"> <line x1="40" y1="15" x2="110" y2="90" style="stroke:purple; stroke-width:6; fill:white;" /> </svg>
L’attribut stroke-linecap= permet de définir les fins de ligne :
- "butt" termine la ligne au pixel près quelle que soir l’épaisseur de la ligne
- "square" le dernier pixel est le centre d’un carré de côté égal à la largeur de la ligne (=butt si l’épaisseur est d’un pixel
- "round" le dernier pixel est le centre d’un demi-cercle qui prolonge la ligne
3. Éléments complexes
3.1 Polygones
Les polygones sont définis par un ensemble de coordonnées de points. L’abscisse et l’ordonnée de chaque point sont reliés par une virgule, ces couples de valeurs sont séparés par une espace. La figure est nécessairement «fermée», c’est-à-dire que le dernier point est relié au premier. Cet élément est sensible aux attributs de couleur et de trait.
<svg width="200px" height="200px" style="border:1px grey solid"> <polygon points="40,40 160,30 180,140 30,180" style="stroke:blue; stroke-width:2; fill:yellow;" /> </svg>
3.2 Polyline
Il s’agit d’un polygone non fermé, qu’il est néanmoins possible de remplir. Les points sont définis leurs abscisse,ordonnée séparées par des espaces. Cet élément est sensible aux attributs de couleur et de trait.
<svg width="200px" height="200px" style="border:1px grey solid"> <polyline points="20,40 100,100 180,50 160,100 180,160 40,140" style="stroke:darkgreen;stroke-width:4;fill:lime;" /> </svg>
3.3 Path
Path est un polyline sophistiqué comprenant des courbes et qui peut utiliser des coordonnées relatives aux précédentes, et donc des valeurs parfois négatives. Cet élément est sensible aux attributs de couleur et de trait.
Segments de droites
<svg width="200px" height="150px" style="border:1px grey solid"> <path d="m 10 20 l 70 70 L 110 50 h 50 v 80 h -70 l 25 -25 m 0 15 l 30 -25" style="stroke:darkgreen;stroke-width:4;fill:lime;" /> </svg>
Les lettres majuscules indiquent des coordonnées absolues, les minuscules des coordonnées relatives, qui peuvent être négatives.
- M = saute à une coordonnée sans rien tracer ; commence un chemin
- L = crée une ligne de la coordonnée actuelle à la coordonnée qui suit ; l si relative
- H = trace une ligne horizontale jusqu’à l’abscisse précisée ; h pour une abscisse relative
- V = trace une ligne verticale jusqu’à l’ordonnée précisée ; v pour une ordonnée relative
- Z «ferme» la figure en reliant le dernier point au premier. Ce n’est effectif que si le chemin n’est pas interrompu par un selon M ou m
Note : Les lettres peuvent être collées aux nombres. M 20 20 h 50 peut s’écrire M20 20h50.
Courbes
Les courbes de Bézier permettent un chemin flexible. Les graphiques ci-dessous indiquent en rouge les points et tangentes qui permettent au navigateur de dessiner les courbes. Ils ont dû être expressément ajoutés mais ne sont pas repris dans l’explicitation du code XML ci-dessous :
<svg width="440" height="240" style="border:1px grey solid"> <path d="M 40 40 C 40 100, 180 100, 140 40" style="stroke:black;stroke-width:2;fill:none" /> <path d="M 40 150 S 100 210, 140 150" style="stroke:black;stroke-width:2;fill:none" /> <path d="M 220 20 Q 280 80, 320 20" style="stroke:black;stroke-width:2;fill:none" /> <path d="M 200 160 Q 260 220, 280 160 T 400 140" style="stroke:black;stroke-width:2;fill:none" /> </svg>
- C pc1x pc1y, pc2x pc2y, x y pour une courbe de Bézier cubique à deux points de contrôle
- S pc1x pc1y, x y pour une courbe de Bézier cubique à un point de contrôle ; permet une suite à C, comme T à Q (voir ci-après)
- Q pc1x pc1y, x y pour une courbe de Bézier quadratique à un point de contrôle
- T x y est un raccourci pour suivre une Q ou autre T ; le point de contrôle automatique (évidé) est opposé au premier point de contrôle par rapport à l’inflexion de la courbe
- Z en fin de chaîne ferme la figure en reliant le dernier point au premier
S et Q paraissent très proches ; néanmoins :
<svg width="200px" height="200px" style="border:1px grey solid"> <path d="M 40 50 Q 120 180, 160 50" style="stroke:red;stroke-width:3;fill:none;stroke-opacity:1" /> <path d="M 40 50 S 120 180, 160 50" style="stroke:green;stroke-width:3;fill:none;stroke-opacity:0.5" /> </svg>
Note : comme pour le graphique précédent, le point de contrôle et les segments tangeants ont été ajoutés mais ne figure pas sur le code expliqué.
Ellipse orientée
- A rx ry rotx 0 1 cx cy permet un arc d’ellipse dont le grand axe est penché (rotx en degrés) ; 0 et 1 sont des drapeaux.
- Z en fin de chaîne relie le dernier point au premier
<svg width="150px" height="120px" style="border:1px grey solid"> <path d="M 110 10 A 20 40 -45 0 1 60 30" style="stroke:black;stroke-width:2;fill:none" /> <path d="M 70 60 A 20 40 -45 0 1 20 80 z" style="stroke:black;stroke-width:2;fill:none" /> </svg>
4. Textes
<svg width="200px" height="140px" style="border:1px grey solid"> <text x="20" y="50" stroke="black" stroke-width="2" fill="none" font-size="48">H-W</text> <text x="10" y="90" stroke="gray" font-size="24">Bonjour, monde!</text> <a href="http://jchr.be/" target="_blank"><text x="100" y="120" fill="#b04">jchr.be</text></a> </svg>
textPath
Pour qu’un texte suive une courbe définie par path :
<svg width="300px" height="240px" style="border:1px grey solid"> <path id="cosh" d="M 20 30 q 150 250, 250 0" stroke="transparent" fill="none" /> <text style="fill:blue;font-size:32px;"> <textPath href="#cosh" startOffset="50">Bonjour, le monde!</textPath> </text> </svg>
5. Image
Pour inclure une image SVG sous forme de fichier, celui-ci doit commencer par <?xml version="1.0" encoding="utf-8"?> et la balise <svg> doit contenir xmlns="http://www.w3.org/2000/svg" pour que FireFox l’affiche. Le logiciel libre inkscape produit ce genre de fichiers, qui sont lus par le logiciel libre Image-Magick et les afficheurs d’images des bureaux GNU/Linux (Plasma, Gnome, Mate-desktop…).
Exemple de fichier d’image SVG sauvegardé sous le nom svg.svg :
<?xml version="1.0" encoding="utf-8"?> <svg width="180" height="50" xmlns="http://www.w3.org/2000/svg" style="background:#fea"> <text x="10" y="30" stroke="black" font-size="18">Bonjour, monde!</text> </svg>
Note : il existe des fichiers compressés SVGZ, mais ils sont déconseillés du fait d’être rarement reconnus.
Afficher un fichier SVG dans une page HTML
Les balises <object> et <iframe> permettent d’afficher un fichier svg.svg dans une page HTML :
<object data="svg.svg" type="image/svg+xml"></object>
<iframe src="svg.svg"></iframe>
Il est également possible d’inclure un fichier SVG (PNG ou JPG) dans une image SVG :
- href="" l’URL de l’image
- x="" l’abcisse du coin supérieur gauche de l’image
- y="" l’ordonnée du coin supérieur gauche de l’image
- width="" largeur de l’image
- height="" la hauteur de l’image
<svg width="300px" height="220px" viewbox="0 0 100 100" style="border:1px solid #777"> <text x="0" y="20" style="font-size:12px;">L’image svg.svg :</text> <image href="svg.svg" x="0" y="30" width="100" height="50" /> </svg>
6. Liens
Tout élément inclut entre <a href=""> et </a> peut servir de lien à cliquer. Dans l’exemple suivant, le disque bleu pointe vers le moteur de recherche duckduckgo.com, «jchr.be» vers le site qui héberge la présente page.
<svg width="200px" height="135px" style="border:1px grey solid"> <a href="http://duckduckgo.com/" target="_blank"><circle cx="60" cy="55" r="40" fill="#40b" /></a> <a href="http://jchr.be/" target="_self"><text x="100" y="115" fill="#b04">jchr.be</text></a> </svg>
- href="" pour encoder l’URL de la page
- hreflang="" definit la langue de la page
- target="" choisit l’onglet dans lequel ouvrir le lien :
- _self charge la cible sur l’onglet actuel
- _blank charge la cible sur un nouvel onglet
- des noms au choix, différents pour des onglets séparés
- _parent et _top concernent les <iframe>
- type="" précise le type MIME de la cible
- download ?permet un téléchargement plutôt que l’ouverture du lien
7. Attributs graphiques
Il peut être judicieux d’insérer les attributs graphiques dans un attribut style="" ou dans des classes, définies entre les balises <style> et </style> de début de page HTML.
stroke="" définit la couleur du trait qui entoure une forme géométrique
La définition d’une couleur peut se faire :
stroke-opacity="" détermine l’opacité du trait-contour
L’opacité va de 0.0 ou transparent à opaque 1.0 (par défaut). Il est possible de la préciser avec un pourcentage dans les formules rgb(24 56 200 / 40%) et hsl(60 80% 60% / 40%)
Il existe deux formes de dégradés : le gradient linéaire et le radial.
linearGradient définit les couleurs et leur proportionnalité selon un sens. l'id="" permet un appel à cette définition de la balise de l'élément coloré
Il est possible d'inverser le sens du dégradé en intervertissant les valeurs de x1 et x2, ou de changer de direction en intervertissant les valeurs des x et des y, voire faire un dégradé oblique en jouant avec ces paramètres.
radialGradient permet un dégradé du centre vers l'extérieur.
Il est possible de décentrer la cocarde de couleur, par exemple avec
spreadMethod="" définit le comportement lors du dépassement de la définition :
+ gradientUnits="objectBoundingBox" ou userSpaceOnUse + gradientTransform
stroke-width="" détermine l’épaisseur du trait-contour de la figure (1 par défaut). Attention : c’est le centre du trait qui satisfait aux grandeurs indiquées.
L’attribut stroke-dasharray="" définit un mode de discontinuité, défini par une succession de nombres précisant successivement la couleur et la transparence ; en cas de nombre impair de nombres, la succession s’inverse. Pour "12 6 2" :
Notes : des pourcentages sont possibles, stroke-dasharray="6% 2%"
L’attribut stroke-linecap="" définit les fins de ligne :
L’attribut stroke-linejoin="" définit les jointures d’angle d’une ligne brisée :
fill-rule, stroke-miterlimit, stroke-dashoffset
offset, offset-path, offset-anchor, offset-distance, offset-path, offset-position, offset-rotate
L'attribut transform="" permet d'appliquer des modifications à un élément ou à un ensemble d'éléments regroupés avec <g></g>. Il est possible d'enchaîner deux ou plusieurs transformations au même élément en les séparant d'une espace :
"translate(,)" déplace un élément sans devoir modifier tous ses attributs de coordonnées.
rotate() opère une rotation de l'élément, le premier paramètre est l'angle de rotation (horaire), transform-origin="dx dy" définit le point fixe de la rotation, mais il semble que transform="rotate(30)" peut également faire l'affaire.
Attention : Lors d'une composition de transformations, la seconde tient compte du changement de coordonnées de la première. Dans l'exemple ci-dessous, la translation «horizontale» devient de ce fait oblique (avec le rectangle bleu comme résultat intermédiaire) :
scale() permet de diminuer ou agrandir un élément ; il est possible de prévoir deux rapports différents pour les dimensions. transform-origin="" détermine le point fixe de la transformation.
skewX() et skewX() provoquent un cisaillement horizontal (rose) et vertical (vert) ; il est possible de préciser le point fixe de la transformation avec transform-origin="x y".
7.1 Couleurs et opacité
fill="" définit la couleur du remplissage de l’intérieur d’une figure, ou de l’épaisseur du trait (text)
fill-opacity="" détermine l’opacité de la couleur du corps de la figure
<svg width="120", height="120" style="border:solid 1px #777">
<rect x="10" y="20" width="100", height="40" fill="#f77" />
<rect x="20" y="10" width="40", height="100" fill="rgb(0 255 255 / 50%)" />
</svg>
Dégradés de couleurs
<svg width="150" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<linearGradient id="rasta" x1="0" y1="0" x2="1" y2="0">
<stop offset="0%" stop-color="darkgreen" />
<stop offset="50%" stop-color="yellow" />
<stop offset="100%" stop-color="red" />
</linearGradient>
</defs>
<rect x="0" y="0" width="150" height="100" fill="url(#rasta)" />
</svg>
<svg width="100" height="100" version="1.1" xmlns="http://www.w3.org/2000/svg">
<defs>
<radialGradient id="cocarde">
<stop offset="0%" stop-color="#0f0" />
<stop offset="70%" stop-color="#0bb" />
<stop offset="100%" stop-color="#d0f" />
</radialGradient>
</defs>
<circle cx="50" cy="50" r="50" fill="url(#cocarde)" />
</svg>
<radialGradient id="cocarde" cx="0.6" cy="0.4" r="0.6">
7.2 Attributs de trait
Largeur de trait
Discontinuité
xxxxxxxxxx······xx··········xxxxxx·· etc.
<svg width="200px" height="200px" style="border:1px grey solid">
<polyline points="20,40 100,100 180,50 160,100 180,160 40,140" stroke-dasharray="10 6 2" stroke-width="4" fill="darkgreen" />
</svg>
Décorations de ligne
<svg width="180px" height="120px" style="border:1px grey solid">
<line x1="30" y1 ="30" x2="30" y2="90" stroke-width="20" stroke-linecap="square" stroke="purple" fill="tranparent" />
<line x1="55" y1 ="30" x2="55" y2="90" stroke-width="1" stroke="black" />
<line x1="80" y1 ="30" x2="80" y2="90" stroke-width="20" stroke-linecap="butt" stroke="purple" />
<line x1="105" y1 ="30" x2="105" y2="90" stroke-width="1" stroke="black" />
<line x1="130" y1 ="30" x2="130" y2="90" stroke-width="20" stroke-linecap="round" stroke="purple" />
</svg>
<svg width="300px" height="160px" style="border:1px grey solid">
<polyline points="30,20 70,60 30,100 70,140" stroke-width="20" stroke-linejoin="miter" stroke="blue" fill="none" />
<polyline points="130,20 170,60 130,100 170,140" stroke-width="20" stroke-linejoin="bevel" stroke="blue" fill="none" />
<polyline points="230,20 270,60 230,100 270,140" stroke-width="20" stroke-linejoin="round" stroke="blue" fill="none" />
</svg>
Et encore…
7.3 Transformations
transform="scale(10,20) rotate(45)"
Translation
<svg width="100" height="100" style="border:1px solid #999">
<circle cx="60" cy="0" r="40" fill="#777" />
<circle cx="60" cy="0" r="40" transform="translate(-20,20)" fill="green" fill-opacity="0.5" />
</svg>
Rotations
<svg width="100" height="100" style="border:1px solid #999">
<ellipse cx="50" cy="50" rx="28" ry="40" fill="#444" />
<ellipse cx="50" cy="50" rx="28" ry="40" transform="rotate(50)" transform-origin="50 50" fill="green" fill-opacity="0.5" />
</svg>
<svg width="100" height="100" style="border:1px solid #777">
<rect x="10" y="20" width="40" height="20" fill="#777" />
<rect x="10" y="20" width="40" height="20" transform="rotate(30)" transform-origin="30 30" fill="blue" fill-opacity="0.5" />
<rect x="10" y="20" width="40" height="20" transform="rotate(30) translate(45,0)" transform-origin="30 30" fill="green" fill-opacity="0.5" />
</svg>
Échelle
<svg width="100" height="100" style="border:1px solid #777">
<rect x="10" y="10" width="40" height="20" fill="#777" />
<rect x="10" y="10" width="40" height="20" transform="scale(1.8)" fill="red" fill-opacity="0.5" />
<rect x="10" y="10" width="40" height="20" transform="scale(0.7,3)" fill="green" fill-opacity="0.5" transform-origin="10 10" />
</svg>
Cisaillements
<svg width="100" height="100" style="border:1px solid #777">
<rect x="10" y="10" width="40" height="20" fill="#777" />
<rect x="10" y="10" width="40" height="20" transform="skewX(30)" fill="red" fill-opacity="0.5" transform-origin="30 20" />
<rect x="10" y="10" width="40" height="20" transform="skewY(45)" fill="green" fill-opacity="0.5" />
</svg>