<foreignObject> in SVG: the doorway back into ordinary HTML

The <foreignObject> element embeds plain HTML inside an SVG's coordinates, giving text real automatic line wrapping at last.
4 min read
Believemy logo

Native SVG text, drawn with <text>, never wraps on its own: a sentence too long for its intended width simply overflows the box, and no font tweak fixes that. On an infographic mixing shapes with explanatory paragraphs, that limit gets in the way fast.

<foreignObject> works around it by opening a window, right inside the SVG's own coordinates, where perfectly ordinary HTML content can be dropped in, with everything HTML already knows how to do, automatic line wrapping included.


Definition

<foreignObject> marks out a rectangle, positioned and sized in SVG coordinates, inside which content belonging to another markup language can be placed, most often HTML. That content is then laid out by the usual rules of HTML and CSS, not by SVG's rules: a paragraph behaves there like an ordinary paragraph, with automatic line breaks, margins, and an inherited font.


Main attributes

Four attributes are enough to frame the area: x and y place the top-left corner of the rectangle, width and height set its width and height. Unlike many other SVG elements, these dimensions are mandatory: without a width and a height set, <foreignObject> reserves no space at all, and its content shows up nowhere.

AttributeRole
x, yPosition of the top-left corner
width, heightDimensions of the area, mandatory


A concrete example

An infographic card combines a background drawn with <rect> and an explanatory paragraph whose exact length is not known ahead of time.

HTML
<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;"
    >
      This paragraph is long enough to show that the text wraps automatically,
      exactly like on an ordinary HTML page.
    </div>
  </foreignObject>
</svg>

The same paragraph written with <text> and <tspan> would have needed the position of every line break worked out by hand, redone each time the text changes.


Difference with <text>

<text> is still the right call for a short label, a large number, or a single-line caption: light, crisp, with no dependency on an external layout engine. The problem shows up once the text length is not known ahead of time, a comment pulled from a database, or a caption translated into a language wordier than the original. With <text>, every word's width would need measuring in JavaScript, with lines broken by hand using <tspan>; with <foreignObject>, the HTML rendering engine does that work on its own, every time the content changes, exactly as it would for any paragraph on an ordinary web page.


Classic trap

Good to know

Content placed inside <foreignObject> must carry the HTML XML namespace, xmlns="http://www.w3.org/1999/xhtml", on its root element, usually a <div>. Without that declaration, some rendering engines, especially outside ordinary web browsers, refuse to show the content or silently drop it. A second trap shows up at export time: converting an SVG that contains a <foreignObject> into a PNG on a server often fails, because many conversion tools simply cannot interpret HTML nested inside SVG.


A real use case

Charting libraries such as D3.js lean on <foreignObject> to show tooltips with variable content, a legend that changes length depending on the data, or a label that must keep ordinary HTML formatting, bold text, links, line breaks, rather than being redrawn as plain <text>. A dashboard built in React or Vue, wrapping an SVG chart with interactive HTML widgets, benefits from the same trick: forms, buttons or search fields can live directly inside the drawing's coordinates, without juggling two separate positioning systems.


Frequently asked questions

Question

Can an image or a form go inside <foreignObject>?

Yes, any valid HTML content fits there, including images, links, or form fields, as long as the XHTML namespace sits on the wrapping element.

Question

Does <foreignObject> work in every browser?

Support is solid across modern web browsers, but gets noticeably shakier once the SVG leaves that context, for example in a PDF export, a server-side image conversion, or certain feed readers.

Question

Does CSS applied to the HTML content behave normally?

Yes, the usual CSS rules, cascade, inheritance, media queries, apply without change to content placed inside <foreignObject>, since it stays HTML through and through: only its position follows the enclosing SVG's coordinates.

Related terms

Discover our hTML and CSS glossary

Browse the terms and definitions most commonly used in HTML and CSS development.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.