Le texte natif d'un SVG, dessiné avec <text>, ne revient jamais à la ligne tout seul : une phrase trop longue pour sa largeur prévue déborde simplement du cadre, sans qu'aucun réglage de police ne corrige le problème. Sur une infographie qui mélange formes et paragraphes explicatifs, cette limite devient vite gênante.
<foreignObject> contourne l'obstacle en ouvrant, à l'intérieur même des coordonnées du SVG, une fenêtre où du contenu HTML tout à fait ordinaire peut être inséré, avec tout ce que le HTML sait déjà faire, y compris le retour à la ligne automatique.
Définition
<foreignObject> délimite un rectangle, positionné et dimensionné en coordonnées SVG, à l'intérieur duquel du contenu appartenant à un autre langage de balisage peut être placé, le plus souvent du HTML. Ce contenu est alors mis en page par les règles habituelles du HTML et du CSS, pas par celles du SVG : un paragraphe s'y comporte comme un paragraphe ordinaire, avec ses retours à la ligne automatiques, ses marges et sa police héritée.
Attributs principaux
Quatre attributs suffisent à cadrer la zone : x et y placent le coin supérieur gauche du rectangle, width et height en fixent la largeur et la hauteur. Contrairement à d'autres éléments SVG, ces dimensions sont obligatoires : sans largeur ni hauteur définies, <foreignObject> ne réserve aucun espace et son contenu n'apparaît nulle part.
| Attribut | Rôle |
|---|---|
x, y | Position du coin supérieur gauche |
width, height | Dimensions de la zone, obligatoires |
Exemple de rendu concret
Une carte d'infographie combine un fond dessiné en <rect> et un paragraphe explicatif dont la longueur exacte n'est pas connue à l'avance.
<svg viewBox="0 0 300 150" xmlns="http://www.w3.org/2000/svg">
<rect width="300" height="150" fill="#eef2ff" rx="12" />
<foreignObject x="20" y="20" width="260" height="110">
<div
xmlns="http://www.w3.org/1999/xhtml"
style="font-family: sans-serif;
font-size: 14px;
color: #1e293b;
line-height: 1.4;"
>
Ce paragraphe est assez long pour montrer que le texte revient
automatiquement à la ligne, exactement comme dans une page HTML classique.
</div>
</foreignObject>
</svg>Le même paragraphe écrit avec <text> et <tspan> aurait exigé de calculer à la main la position de chaque retour à la ligne, un travail refait à chaque fois que le texte change.
Différence avec <text>
<text> reste le bon choix pour un court libellé, un chiffre affiché en grand ou une légende d'une seule ligne : léger, net, sans dépendance à un moteur de mise en page externe. Le problème apparaît dès que la longueur du texte n'est pas connue à l'avance, un commentaire généré depuis une base de données, ou une légende traduite dans une langue plus verbeuse que l'originale. Avec <text>, il faudrait mesurer la largeur de chaque mot en JavaScript et couper les lignes à la main avec <tspan> ; avec <foreignObject>, le moteur de rendu HTML fait ce calcul tout seul, à chaque changement de contenu, exactement comme il le ferait pour n'importe quel paragraphe d'une page web ordinaire.
Piège classique
Le contenu placé à l'intérieur de <foreignObject> doit porter l'espace de noms XML du HTML, xmlns="http://www.w3.org/1999/xhtml", sur son élément racine, en général un <div>. Sans cette déclaration, certains moteurs de rendu, en particulier hors des navigateurs web classiques, refusent d'afficher le contenu ou l'ignorent silencieusement. Un second piège guette à l'export : convertir un SVG contenant un <foreignObject> en image PNG côté serveur échoue souvent, car beaucoup d'outils de conversion ne savent tout simplement pas interpréter du HTML imbriqué dans du SVG.
Cas d'usage réel
Les bibliothèques de graphiques comme D3.js s'appuient sur <foreignObject> pour afficher des info-bulles au contenu variable, une légende qui change de longueur selon les données, ou un libellé qui doit absolument garder la mise en forme HTML habituelle, gras, liens, sauts de ligne, plutôt que d'être redessiné en <text> appauvri. Un tableau de bord construit en React ou en Vue, qui entoure un graphique SVG de widgets HTML interactifs, profite de la même logique : formulaires, boutons ou champs de recherche peuvent vivre directement dans les coordonnées du dessin, sans jongler entre deux systèmes de positionnement séparés.
Questions fréquentes
Peut-on mettre une image ou un formulaire dans <foreignObject> ?
Oui, n'importe quel contenu HTML valide y trouve sa place, y compris des images, des liens ou des champs de formulaire, du moment que l'espace de noms XHTML est posé sur l'élément englobant.
<foreignObject> fonctionne-t-il dans tous les navigateurs ?
Le support est bon sur les navigateurs web modernes, mais nettement plus fragile dès que le SVG sort de ce contexte, par exemple dans un export PDF, une conversion en image côté serveur ou certains lecteurs de flux.
Le CSS appliqué au contenu HTML se comporte-t-il normalement ?
Oui, les règles CSS habituelles, la cascade, l'héritage, les media queries, s'appliquent sans changement au contenu placé dans <foreignObject>, puisqu'il reste du HTML en tout point : seule sa position obéit aux coordonnées du SVG englobant.