frontend / html
SVG inline et manipulation
Explication
Ce que vous allez apprendre
- Comprendre pourquoi le SVG reste manipulable en DOM contrairement au Canvas
- Utiliser
viewBoxpour définir un repère de coordonnées interne indépendant de l'affichage - Styliser un SVG inline en CSS, y compris au survol avec
:hover - Créer dynamiquement un élément SVG en JavaScript avec
createElementNS - Réutiliser des formes avec
<defs>/<use>et faire hériter une couleur aveccurrentColor
Dans quel contexte ?
Un designer demande qu'une icône de panier dans header.html change de couleur au survol de la souris, en cohérence avec la charte graphique. Si l'icône est une image PNG classique, c'est impossible sans dupliquer le fichier ; en l'intégrant comme SVG inline avec fill="currentColor", un simple .icone:hover { color: #1d4ed8; } en CSS suffit, exactement comme pour n'importe quel texte du DOM.
Étape 1 : la limite du Canvas, rappel rapide
La leçon précédente montrait le Canvas, qui dessine des pixels sans laisser de trace structurée derrière lui — impossible de "cliquer sur le cercle" après coup, puisqu'il n'existe plus qu'une image.
Étape 2 : l'approche inverse du SVG
Le SVG prend l'approche inverse : chaque forme reste un vrai élément du DOM, aussi manipulable qu'une balise HTML classique. Un <circle> peut recevoir un addEventListener, être ciblé en CSS, exactement comme un <div>.
Étape 3 : pourquoi c'est "vectoriel"
La différence fondamentale avec une image bitmap (JPEG, PNG) est que le SVG décrit des FORMES mathématiques — un cercle a un centre et un rayon — plutôt que des pixels fixes.
Étape 4 : la conséquence concrète de ce choix
Résultat : agrandir un SVG à n'importe quelle taille ne le rend jamais flou ni pixelisé, contrairement à une photo zoomée. C'est pour cela que les icônes et logos modernes utilisent presque toujours ce format.
| Critère | Canvas | SVG |
|---|---|---|
| Nature | Pixels (bitmap) | Formes vectorielles (DOM) |
| Manipulable après dessin ? | Non (image figée) | Oui (querySelector, CSS, events) |
| Agrandissement | Devient flou/pixelisé | Toujours net |
| Cas d'usage typique | Jeux, animations complexes | Icônes, logos, graphiques interactifs |
Étape 5 : le repère caché mais essentiel, viewBox
Il reste un attribut à comprendre absolument : viewBox définit un système de coordonnées interne, indépendant de la taille d'affichage réelle en pixels CSS. Comme dessiner sur du papier millimétré dont on change ensuite la taille d'impression sans toucher au dessin.
Le piège de la création dynamique
Un dernier piège technique : créer un élément SVG en JavaScript avec le simple document.createElement échoue silencieusement, sans erreur visible. La raison : le SVG appartient à un "espace de noms" XML différent du HTML classique.
Il faut donc utiliser createElementNS en précisant explicitement ce namespace pour que le navigateur reconnaisse l'élément comme du SVG valide.
Piège fréquent
document.createElement("circle") ne lève aucune erreur mais crée un élément HTML inconnu, invisible et sans effet, jamais un vrai cercle SVG. Utilisez systématiquement document.createElementNS("http://www.w3.org/2000/svg", "circle") pour créer un élément SVG en JavaScript.
Et ensuite ?
Une fois SVG et Canvas maîtrisés, la prochaine leçon aborde un sujet de sécurité important : intégrer du contenu tiers avec les iframes et le sandboxing.
Commandes & code
SVG inline et manipulation
Graphiques vectoriels directement dans le DOM, stylables en CSS et manipulables en JS comme n'importe quel élément.
<!-- SVG inline : fait partie du DOM, contrairement à <img src="x.svg"> -->
<svg viewBox="0 0 200 200" width="200" height="200" xmlns="http://www.w3.org/2000/svg">
<!-- viewBox définit le repère interne : indépendant de width/height affichés -->
<circle cx="100" cy="100" r="80" fill="#2563eb" class="cercle-principal" />
<rect x="60" y="60" width="80" height="80" fill="#f59e0b" opacity="0.8" />
<text x="100" y="105" text-anchor="middle" fill="#fff" font-size="14">SVG</text>
</svg><!-- Chemins : la primitive la plus puissante, base de toute icône complexe -->
<svg viewBox="0 0 24 24" width="24" height="24">
<path
d="M12 2 L15 9 L22 9 L16.5 13.5 L18.5 21 L12 17 L5.5 21 L7.5 13.5 L2 9 L9 9 Z"
fill="#f59e0b"
/>
<!-- M = moveto, L = lineto, Z = close path — commandes en majuscule = coordonnées
absolues, en minuscule = relatives à la position courante -->
</svg>
<!-- Dégradés et réutilisation via <defs>/<use> -->
<svg viewBox="0 0 200 100" width="200" height="100">
<defs>
<linearGradient id="degrade1" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" stop-color="#2563eb" />
<stop offset="100%" stop-color="#22c55e" />
</linearGradient>
<circle id="pastille" r="10" fill="#fff" />
</defs>
<rect width="200" height="100" fill="url(#degrade1)" />
<use href="#pastille" x="30" y="50" />
<use href="#pastille" x="100" y="50" />
<use href="#pastille" x="170" y="50" />
</svg>/* SVG inline : stylable comme du HTML classique, y compris au survol */
.cercle-principal {
transition: r 0.2s ease, fill 0.2s ease;
}
.cercle-principal:hover {
r: 90;
fill: #1d4ed8;
}
/* currentColor : hérite la couleur du texte environnant, très utile pour les icônes */
svg.icone { fill: currentColor; width: 1em; height: 1em; }// Manipulation en JS : SVG = DOM, donc querySelector/setAttribute fonctionnent
const cercle = document.querySelector(".cercle-principal");
cercle.addEventListener("click", () => {
const rayonActuel = Number(cercle.getAttribute("r"));
cercle.setAttribute("r", rayonActuel === 80 ? 60 : 80);
});
// Créer un élément SVG dynamiquement : namespace obligatoire,
// createElement seul (sans NS) échoue silencieusement sur du SVG
const NS = "http://www.w3.org/2000/svg";
const nouveauCercle = document.createElementNS(NS, "circle");
nouveauCercle.setAttribute("cx", "50");
nouveauCercle.setAttribute("cy", "50");
nouveauCercle.setAttribute("r", "20");
nouveauCercle.setAttribute("fill", "#ef4444");
document.querySelector("svg").appendChild(nouveauCercle);Résumé
- Un SVG inline fait partie du DOM :
querySelector,addEventListener, CSS s'y appliquent directement. viewBoxdéfinit le système de coordonnées interne, indépendamment dewidth/heighten pixels CSS.- Créer un élément SVG en JS exige
createElementNSavec le namespace SVG, pascreateElement. currentColorsurfill/strokefait hériter une icône SVG de la couleur du texte parent.
Exercices pratiques
Mission : rendre l'icône panier de header.html réactive au survol
Objectif : Remplacer une icône PNG figée par un SVG inline capable de changer de couleur au survol via CSS pur.
Contexte
Un designer demande qu'une icône de panier dans header.html change de couleur au survol de la souris, en cohérence avec la charte graphique. L'icône est actuellement une image <img src="panier.png">. Le designer a aussi remarqué que redimensionner cette icône en CSS (width: 32px) la fait parfois apparaître rognée plutôt que proprement mise à l'échelle sur d'autres icônes SVG du site.
Ta mission : intégrer l'icône en SVG inline, stylable au survol.