tutorial/langage-svg.md

Apprendre le langage SVG, pas Ă  pas

Public visé : vous connaissez un peu HTML/CSS, mais vous n'avez jamais (ou peu) écrit de SVG à la main. À la fin, vous saurez lire et composer un document SVG complet — structure, formes, styles, chemins, réutilisation, transformations, texte, dégradés, découpes, filtres et animations — en le tapant vous-même.

Le SVG (Scalable Vector Graphics) est un format d'image vectorielle décrit en XML. Contrairement à une image matricielle (PNG, JPEG), il ne stocke pas des pixels mais des instructions de dessin : « trace un cercle ici », « remplis cette forme ». D'où ses deux qualités : il reste net à n'importe quelle taille, et son code est du texte lisible, versionnable, modifiable à la main.

C'est un tutoriel : chaque étape s'appuie sur la précédente et le chemin décrit ici fonctionne. Suivez-le dans l'ordre.

Ce dont vous avez besoin

  • Un Ă©diteur de texte (n'importe lequel) et un fichier .svg.
  • Un navigateur pour voir le rendu : ouvrez-y le fichier, ou collez le code dans une page HTML.

Écrivez chaque exemple, regardez le rendu, modifiez une valeur, regardez à nouveau. C'est en déplaçant les nombres vous-même que le repère de coordonnées devient une intuition.

Les exemples s'appuient sur SVG 2, la spécification du W3C. Les liens de référence sont regroupés en fin de tutoriel.


Étape 1 — La structure : un document SVG minimal

Un SVG est avant tout un document XML : chaque balise doit être correctement fermée. Créez un fichier et tapez le strict minimum.

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="120" viewBox="0 0 200 120">
  <rect x="10" y="10" width="180" height="100" fill="none" stroke="black"/>
</svg>

Ouvrez le fichier dans un navigateur : vous devez voir un rectangle au trait noir. Tant que ce n'est pas le cas, ne passez pas Ă  la suite.

Ce que vous venez d'écrire :

  • <svg> est la balise racine. L'attribut xmlns dĂ©clare l'espace de noms SVG : sans lui, le navigateur ne traite pas le fichier comme du SVG. C'est l'erreur numĂ©ro un du dĂ©butant.
  • width et height fixent la taille affichĂ©e du dessin.
  • viewBox dĂ©finit l'espace de dessin interne — on y revient Ă  l'Ă©tape 2.
  • <rect> dessine un rectangle ; fill="none" le laisse creux, stroke lui donne un contour.

Exercice — Ajoutez, juste après la balise <svg>, un <title>Mon dessin</title>. C'est le nom de l'image ; nous verrons son rôle à l'étape 10.

Étape 2 — Le repère : coordonnées, viewBox et unités

Tout se joue sur un repère à deux axes : X vers la droite, Y vers le bas (attention, Y descend, contrairement aux mathématiques). L'origine (0, 0) est en haut à gauche.

La subtilité, c'est la viewBox. Elle vaut min-x min-y largeur hauteur et définit un repère logique, indépendant de la taille affichée.

<svg xmlns="http://www.w3.org/2000/svg" width="400" height="200" viewBox="0 0 100 50">
  <rect x="0" y="0" width="100" height="50" fill="#f2f2f2" stroke="#333"/>
  <circle cx="50" cy="25" r="10" fill="#3a6ea5"/>
</svg>

Ici le dessin raisonne dans un espace de 100 × 50 « unités utilisateur », mais il est affiché sur 400 × 200 pixels. Chaque unité logique est donc étirée par quatre. C'est tout l'intérêt du vectoriel : vous dessinez dans un repère confortable, le navigateur met à l'échelle sans perte.

Ă€ retenir :

  • viewBox mappe un repère logique vers la taille affichĂ©e.
  • L'unitĂ© par dĂ©faut est l'« unitĂ© utilisateur », souvent proche du pixel.
  • Les valeurs en % se calculent sur la boĂ®te d'affichage.

Exercice — Changez la viewBox en 0 0 200 100 sans toucher au reste, et observez comment le cercle rapetisse : il occupe désormais une plus petite fraction du repère.

Étape 3 — Les formes de base

Avant les chemins libres, SVG offre des formes prêtes à l'emploi, idéales pour des icônes simples.

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="140" viewBox="0 0 220 140">
  <rect x="10" y="10" width="60" height="40" rx="6" fill="#f2c94c"/>
  <circle cx="120" cy="30" r="20" fill="#3a6ea5"/>
  <ellipse cx="180" cy="30" rx="25" ry="15" fill="#2d9cdb"/>
  <line x1="10" y1="80" x2="210" y2="80" stroke="#333" stroke-width="2"/>
  <polyline points="10,110 60,90 110,110 160,90 210,110" fill="none" stroke="#0f2d40" stroke-width="2"/>
  <polygon points="60,130 90,100 120,130" fill="#eb5757"/>
</svg>
  • rect : rectangle ; rx/ry arrondissent les coins.
  • circle : cercle dĂ©fini par son centre cx/cy et son rayon r.
  • ellipse : deux rayons, rx et ry.
  • line : un segment entre (x1, y1) et (x2, y2).
  • polyline : une suite de points non fermĂ©e.
  • polygon : une suite de points fermĂ©e automatiquement.

La seule différence entre polyline et polygon est cette fermeture : le polygone relie son dernier point au premier.

Exercice — Transformez la polyline en polygon et donnez-lui un stroke : vous verrez le côté de fermeture apparaître.

Étape 4 — Le style : peindre les formes

Deux propriétés gouvernent l'apparence : fill (l'intérieur) et stroke (le contour). Vous pouvez les poser en attributs de présentation directement sur l'élément, ou les mutualiser en CSS.

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="130" viewBox="0 0 220 130">
  <style>
    .accent { fill: #3a6ea5; stroke: #0f2d40; stroke-width: 3; }
  </style>
  <rect x="10" y="10" width="80" height="60" class="accent"/>
  <circle cx="150" cy="40" r="25" fill="none" stroke="#333" stroke-width="4" stroke-dasharray="6 4"/>
  <rect x="120" y="80" width="80" height="40" fill="#f2c94c" opacity="0.7"/>
</svg>
  • Les attributs de prĂ©sentation (fill, stroke, stroke-width…) sont les plus simples pour dĂ©marrer.
  • Une balise <style> avec des classes CSS Ă©vite de rĂ©pĂ©ter le mĂŞme style sur plusieurs Ă©lĂ©ments.
  • stroke-dasharray="6 4" trace un trait en pointillĂ©s (6 unitĂ©s de trait, 4 de vide).
  • opacity rend l'Ă©lĂ©ment entier translucide. Ă€ distinguer de fill-opacity, qui n'agit que sur le remplissage.

Exercice — Remplacez opacity="0.7" par fill-opacity="0.7" sur le rectangle jaune et comparez : le contour, lui, redevient opaque.

Étape 5 — Les chemins (path) : dessiner librement

Le <path> est l'élément le plus puissant. Toutes les autres formes pourraient s'y ramener. Il tient dans un seul attribut, d, une suite de commandes.

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="120" viewBox="0 0 240 120">
  <path d="M10 90 L60 20 L110 90 Z" fill="#f2c94c" stroke="#333" stroke-width="2"/>
  <path d="M140 90 C140 20 220 20 220 90" fill="none" stroke="#3a6ea5" stroke-width="3"/>
</svg>

Les commandes essentielles :

  • M x y — move to : dĂ©place le curseur sans tracer (point de dĂ©part).
  • L x y — line to : trace une ligne droite jusqu'au point.
  • Z — ferme le chemin en rejoignant le point de dĂ©part.
  • C x1 y1 x2 y2 x y — courbe de BĂ©zier cubique (deux points de contrĂ´le).
  • Q x1 y1 x y — courbe de BĂ©zier quadratique (un seul point de contrĂ´le).

Règle transversale : une commande majuscule utilise des coordonnées absolues (depuis l'origine), sa version minuscule des coordonnées relatives (depuis le point courant). L 60 20 va au point (60, 20) ; l 60 20 avance de 60 vers la droite et 20 vers le bas.

Exercice — Remplacez la courbe C du second chemin par une courbe Q (un seul point de contrôle) et observez comment la forme change.

Étape 6 — Réutiliser : g, defs et use

Dès qu'un dessin se complexifie, on veut grouper et réutiliser. Trois outils répondent à ce besoin.

<svg xmlns="http://www.w3.org/2000/svg" width="240" height="120" viewBox="0 0 240 120">
  <defs>
    <g id="badge">
      <circle cx="20" cy="20" r="16" fill="#3a6ea5"/>
      <text x="20" y="25" text-anchor="middle" font-size="10" fill="white">SVG</text>
    </g>
  </defs>
  <use href="#badge" x="10" y="10"/>
  <use href="#badge" x="80" y="10"/>
  <use href="#badge" x="150" y="10"/>
</svg>
  • <g> regroupe plusieurs Ă©lĂ©ments. Un style ou une transformation posĂ© sur le <g> s'applique Ă  tous ses enfants.
  • <defs> contient des Ă©lĂ©ments dĂ©finis mais non dessinĂ©s directement : une bibliothèque de motifs Ă  instancier plus tard.
  • <use href="#id"> instancie un Ă©lĂ©ment dĂ©fini ailleurs. Ici, un seul badge dĂ©crit, dessinĂ© trois fois Ă  des positions diffĂ©rentes.

C'est le principe « définir une fois, réutiliser partout », qui allège le code et garantit la cohérence.

Exercice — Ajoutez transform="scale(1.2)" au deuxième <use> pour l'agrandir. La transformation est le sujet de l'étape suivante.

Étape 7 — Les transformations

Une transformation déplace, agrandit ou fait pivoter un élément (ou un groupe). Elle se pose dans l'attribut transform.

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120" viewBox="0 0 220 120">
  <g transform="translate(20 20) rotate(10)">
    <rect x="0" y="0" width="80" height="40" fill="#f2c94c"/>
  </g>
  <rect x="140" y="20" width="60" height="60" fill="#3a6ea5" transform="scale(1.1)"/>
</svg>
  • translate(dx dy) — dĂ©place.
  • scale(facteur) — met Ă  l'Ă©chelle (attention : agrandit aussi la distance Ă  l'origine).
  • rotate(angle) — fait tourner autour de l'origine ; rotate(angle cx cy) fait tourner autour du point (cx, cy).

Deux points clés :

  • Les transformations se cumulent dans l'ordre d'Ă©criture : translate(...) rotate(...) dĂ©place d'abord, puis tourne dans le repère dĂ©placĂ©. Inverser l'ordre change le rĂ©sultat.
  • PosĂ©e sur un <g>, la transformation affecte tout le groupe d'un coup.

Exercice — Faites tourner le second rectangle autour de son propre centre avec rotate(angle cx cy), en calculant cx/cy au milieu du rectangle.

Étape 8 — Le texte

Le texte SVG est du vrai texte : sélectionnable, zoomable, indexable — pas une image de lettres.

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120" viewBox="0 0 220 120">
  <defs>
    <path id="arc" d="M20 80 Q110 10 200 80"/>
  </defs>
  <text x="20" y="30" font-size="14">Texte simple</text>
  <text font-size="14" fill="#3a6ea5">
    <textPath href="#arc">Texte sur un chemin</textPath>
  </text>
</svg>
  • <text> se positionne par x/y (le y est la ligne de base, pas le haut des lettres).
  • <tspan> permet de styler ou repositionner une portion du texte (un mot en gras, un retour Ă  la ligne manuel).
  • <textPath href="#id"> fait suivre un chemin au texte, en s'appuyant sur un <path> dĂ©fini dans <defs>.

Exercice — Enveloppez un mot du « Texte simple » dans un <tspan font-weight="bold">…</tspan> pour le mettre en gras.

Étape 9 — Dégradés et motifs (paint servers)

fill et stroke n'acceptent pas que des couleurs unies : ils acceptent aussi des serveurs de peinture — dégradés et motifs — définis dans <defs> et référencés par url(#id).

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120" viewBox="0 0 220 120">
  <defs>
    <linearGradient id="grad" x1="0" y1="0" x2="1" y2="0">
      <stop offset="0%" stop-color="#3a6ea5"/>
      <stop offset="100%" stop-color="#f2c94c"/>
    </linearGradient>
    <pattern id="grid" width="8" height="8" patternUnits="userSpaceOnUse">
      <path d="M8 0 H0 V8" fill="none" stroke="#ccc" stroke-width="1"/>
    </pattern>
  </defs>
  <rect x="10" y="10" width="90" height="60" fill="url(#grad)"/>
  <rect x="120" y="10" width="90" height="60" fill="url(#grid)"/>
</svg>
  • <linearGradient> — un dĂ©gradĂ© linĂ©aire, dont la direction est donnĂ©e par x1,y1 → x2,y2. Chaque <stop> place une couleur Ă  un offset (de 0 % Ă  100 %).
  • <radialGradient> — mĂŞme principe, mais rayonnant depuis un centre.
  • <pattern> — un motif rĂ©pĂ©tĂ© qui pave la forme.
  • On les applique toujours via fill="url(#id)".

Exercice — Remplacez linearGradient par radialGradient (en retirant les attributs de direction) et observez le dégradé rayonner du centre.

Étape 10 — Découper et masquer (clipPath, mask)

Deux techniques pour ne montrer qu'une partie d'un dessin, avec une logique différente.

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120" viewBox="0 0 220 120">
  <defs>
    <clipPath id="clip">
      <circle cx="60" cy="60" r="40"/>
    </clipPath>
    <mask id="fade">
      <rect width="220" height="120" fill="white"/>
      <rect x="110" y="0" width="110" height="120" fill="black"/>
    </mask>
  </defs>
  <rect width="220" height="120" fill="#f2c94c"/>
  <rect width="220" height="120" fill="#3a6ea5" clip-path="url(#clip)"/>
  <rect width="220" height="120" fill="#0f2d40" mask="url(#fade)"/>
</svg>
  • <clipPath> dĂ©coupe selon une forme gĂ©omĂ©trique : ce qui est dedans reste, ce qui est dehors disparaĂ®t. C'est une dĂ©coupe franche, tout ou rien.
  • <mask> module la transparence par niveaux de gris : le blanc laisse voir, le noir cache, les gris rendent semi-transparent. D'oĂą les dĂ©gradĂ©s de disparition (le fade).

Retenez la distinction : le clip est une paire de ciseaux, le masque est un calque de transparence.

Exercice — Remplacez le <circle> du clipPath par un <polygon> pour découper selon une forme anguleuse.

Étape 11 — Les filtres

Les filtres appliquent des effets de traitement d'image (flou, désaturation…) via un <filter> composé de primitives.

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120" viewBox="0 0 220 120">
  <defs>
    <filter id="blur">
      <feGaussianBlur stdDeviation="3"/>
    </filter>
    <filter id="mono">
      <feColorMatrix type="saturate" values="0"/>
    </filter>
  </defs>
  <circle cx="60" cy="60" r="30" fill="#3a6ea5" filter="url(#blur)"/>
  <rect x="120" y="30" width="70" height="60" fill="#f2c94c" filter="url(#mono)"/>
</svg>
  • <feGaussianBlur stdDeviation="…"> — un flou gaussien ; plus stdDeviation est grand, plus c'est flou.
  • <feColorMatrix type="saturate" values="0"> — ici une dĂ©saturation complète (noir et blanc).
  • On applique un filtre via filter="url(#id)".
  • Un mĂŞme <filter> peut enchaĂ®ner plusieurs primitives, la sortie de l'une alimentant l'entrĂ©e de la suivante.

Note de performance : les filtres peuvent être coûteux à calculer, surtout sur mobile. Utilisez-les avec parcimonie.

Exercice — Augmentez stdDeviation du filtre blur et observez le flou s'intensifier.

Étape 12 — Animer

On peut animer un SVG sans JavaScript, avec les balises d'animation SMIL.

<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120" viewBox="0 0 220 120">
  <circle cx="20" cy="60" r="18" fill="#3a6ea5">
    <animate attributeName="cx" from="20" to="200" dur="2s" repeatCount="indefinite"/>
  </circle>
</svg>
  • <animate> fait varier un attribut (ici cx) de from Ă  to sur une durĂ©e dur. repeatCount="indefinite" boucle sans fin.
  • <animateTransform> anime une transformation (rotation, translation, Ă©chelle) plutĂ´t qu'un simple attribut.

Deux points de compatibilité, à connaître avant de choisir SMIL :

  • Le support de SMIL varie selon les navigateurs et n'est pas garanti partout.
  • Pour de la robustesse, on anime souvent transform ou opacity en CSS, qui offre un support plus homogène.

Gardez les animations simples : c'est le meilleur gage de compatibilité.

Exercice — Remplacez <animate> par un <animateTransform> de type rotate pour faire tourner un élément.

Assembler : un dessin complet

Vous avez maintenant toutes les briques. Un SVG riche les combine dans un ordre naturel :

  1. La structure (<svg>, xmlns, viewBox) pose le cadre.
  2. <defs> regroupe les ressources réutilisables : dégradés, motifs, clipPath, mask, filtres, éléments à instancier.
  3. Le corps du dessin assemble formes et chemins, organisés en <g>, peints avec fill/stroke ou des serveurs de peinture, positionnés par des transform, complétés de <text>.
  4. Découpes, masques et filtres affinent le rendu ; les balises d'animation lui donnent vie.

Reprenez chaque étape comme une couche que vous empilez consciemment, plutôt que comme une liste d'options isolées.

Pour aller plus loin

  • L'accessibilitĂ© du SVG est un sujet Ă  part entière : un dessin neuf est muet pour un lecteur d'Ă©cran tant qu'on ne lui ajoute pas, explicitement, un <title>, une <desc>, les rĂ´les ARIA — ou qu'on ne le masque pas s'il est dĂ©coratif. Ce parcours est traitĂ© dans le tutoriel dĂ©diĂ© « Produire un SVG accessible, pas Ă  pas », Ă  suivre après celui-ci.
  • GĂ©nĂ©rer du SVG par programme : puisque c'est du texte, un langage serveur ou client peut le produire dynamiquement (graphiques, badges, visualisations de donnĂ©es).

Références W3C

Assistant documentaire

Posez une question sur la documentation. Les réponses citent leurs sources — un clic ouvre le document à gauche.