Skip to content
HomeBlogText and fonts in SVG
Fundamentals

Text in SVG: When to Outline Fonts and When to Keep Them Live

SM
SVG Maker AI
June 24, 2026
5 min read

A word in an SVG is either characters or geometry, and the two behave nothing alike. Characters stay searchable and weigh almost nothing, but they render only where the font is available. Geometry renders identically everywhere and is no longer text to anything at all. Most of the trouble with type in SVG comes from picking one without knowing you had picked.

1. Three ways to put words in a drawing

three_ways.svg
<!-- 1. Live text. Real characters — selectable,
     searchable, translatable, and about forty bytes.
     Renders correctly only where the font resolves. -->
<text x="10" y="40" font-family="Inter" font-size="24">Ship it</text>

<!-- 2. Outlined. The same word as geometry. Renders
     identically everywhere and is no longer text to
     anything: not to search, not to a screen reader,
     not to copy and paste. -->
<path d="M10 40h4l2-8h1l2 8h4l-4-14h-5z ..." />

<!-- 3. Live text plus the font embedded in the file.
     Both properties at once, paid for in bytes and
     in licence terms. -->

The decision is usually made for you by where the file is going. A logo bound for a print shop or a cutting machine has to be outlined, because nothing downstream has your font. An SVG rendered inside your own site can stay live text, because your stylesheet has already loaded the typeface. A file that must travel and stay editable wants the third option.

2. Live text depends on a font you do not control

font-family="Inter" is a request, not a guarantee. It resolves against fonts available to whatever is doing the rendering — a browser, Illustrator, a plotter's driver, a printer's RIP — and when it fails the substitution is silent. The text does not disappear; it reflows in a default serif at different widths, so a carefully positioned wordmark quietly becomes a different shape.

This is why print shops ask for outlines rather than trusting you to send the font, and why it is the single most common reason a file that looked right on your screen comes back wrong.

3. The rule that breaks the usual advice

The standard fix — import a web font inside the SVG's own <style> block — does not work in the case that needed it.

why_import_fails.svg
<!-- This is the pattern most tutorials show, and it
     fails in the case you needed it for. -->
<svg xmlns="http://www.w3.org/2000/svg">
  <style>
    @import url("https://fonts.googleapis.com/css2?family=Inter");
  </style>
  <text font-family="Inter" x="10" y="40">Ship it</text>
</svg>

<!-- An SVG loaded through <img>, a CSS background or
     an <object> is rendered in a restricted mode: no
     scripts, and no external references of any kind.
     Fonts, stylesheets and images are all blocked, so
     the @import is never fetched and the text falls
     back to a default serif.

     Inline in the HTML it does work — but there the
     page has already loaded Inter and the @import is
     redundant. It helps only where it is unnecessary,
     and fails everywhere it was the point. -->

An SVG used as an image is rendered in a restricted mode that blocks every external reference: no fonts, no stylesheets, no images, no scripts. The @import is never requested. Inline in your HTML it does work — but inline, the page has already loaded the font, so the import was never needed. It helps only where it is redundant and fails everywhere it was the point, which makes it one of the more expensive pieces of received wisdom in this area.

4. Outlining: what it costs

Converting text to outlines replaces each character with the path that draws it. The word renders identically on every machine forever. What you give up is everything that made it text:

  • Editing. It is a one-way operation. Fixing a typo means redoing the conversion from the original text, so keep a live copy.
  • Search and indexing. The words are no longer in the document.
  • Screen readers and translation. Outlined type is shapes, not language.
  • File size. A short word of live text is tens of bytes. As outlines it is hundreds or thousands, and a paragraph is unusable.

It is worth being precise about the vocabulary, because the wrong word implies the wrong process: outlining is not tracing. Nothing is being detected or approximated. The outlines already exist inside the font file as vector contours, and the conversion copies them out — which is why the result is exact rather than an interpretation.

5. Counters, and why letters break apart

The letters with holes in them — a, e, o, p, g — are drawn as two contours in one path, with the inner one wound the opposite way so the fill rule punches it out. This is where outlining goes wrong in practice.

Split a converted word into separate paths per shape and the counters become their own filled blobs: an "o" turns into a solid disc with a smaller disc on top of it. Modern editors have a dedicated operation that handles this correctly — Inkscape's Flatten rather than the older object-to-path route — and it is worth using the right one rather than fixing the result by hand. If a converted logo comes back with filled-in letters, this is almost always why, and the fix is the winding rule, not the geometry.

6. How to actually do it

There is no browser API for this. Nothing exposes the path data of rendered text, which is why every answer to the question is a tool rather than a snippet — Illustrator's Create Outlines, Inkscape's Flatten, Figma's Flatten Selection, or a library that parses the font file directly.

outline.js
// The browser will not hand you glyph outlines. There
// is no API that returns path data for rendered text,
// which is why every answer to this question is a tool
// rather than a snippet. To do it in code, read the
// font file yourself.

import opentype from "opentype.js"

const font = await opentype.load("/fonts/Inter-Bold.woff")
const path = font.getPath("Ship it", 10, 40, 24)

document.querySelector("#out").innerHTML = path.toSVG(2)
// -> <path d="M10 40h4l2-8..."/>

// Note this is glyph lookup, not full text shaping.
// Ligatures, kerning pairs and scripts that reorder or
// join letters need a real shaping engine — HarfBuzz —
// or the output will be subtly wrong in ways that are
// hard to see in Latin and obvious in Arabic.

The shaping caveat in that sample matters more than it looks. Reading glyphs one at a time gets you Latin text that is very slightly wrong — missing ligatures and kerning pairs — and gets you Arabic or Devanagari that is badly wrong, because those scripts join and reorder. If the text is not simple Latin, use a tool built on a shaping engine.

7. Embedding the font instead

The third option keeps the text live and removes the dependency by putting the font inside the file as a data URI. The characters stay real, and nothing has to be fetched.

embedded_font.svg
<!-- The version that survives being a file: the font
     travels inside it, so nothing has to be fetched.
     Subset it to the characters you actually use, or
     you are shipping a few hundred kilobytes to draw
     one word. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 60">
  <defs>
    <style>
      @font-face {
        font-family: "Wordmark";
        src: url("data:font/woff2;base64,d09GMgABAAAAAA...")
             format("woff2");
      }
      .headline { font-family: "Wordmark"; font-size: 24px; }
    </style>
  </defs>
  <text x="10" y="40" class="headline">Ship it</text>
</svg>

Two things to check before reaching for it. Subset the font to the characters you use — a full family is easily several hundred kilobytes, which is absurd next to a word. And read the licence: plenty of commercial fonts permit web use but forbid embedding in a distributable file, and a base64 blob in an SVG is about as distributable as it gets.

8. Give the words back to everyone else

Whichever you choose, outlined type has left the document as language, so the meaning has to be restored deliberately.

wordmark.svg
<!-- Outlined type is invisible to search engines and
     to screen readers. Give the graphic its name back,
     or the words are simply gone. -->
<svg viewBox="0 0 200 60" role="img"
     aria-labelledby="wordmark"
     xmlns="http://www.w3.org/2000/svg">
  <title id="wordmark">Ship it</title>
  <path d="M10 40h4l2-8..." />
</svg>

A title element on the graphic covers screen readers and gives search engines something to read. If the words are important to the page rather than decorative — a headline set in a display face, say — put them in real HTML as well and let the SVG be the picture of them. More on the patterns in the accessibility guide.

Where to go next

Where our tools sit in this, plainly: the editor places live <text> elements and defaults them to Inter, so an exported file carries exactly the font dependency described in section 2 — check it opens correctly wherever it is going. There is no outline-the-text operation: converting a character to a path needs the font file parsed, and we do not do that, so a design headed for a printer or a cutter needs outlining in a vector editor first.

The optimiser is at least careful around type: it will not collapse whitespace between elements when the drawing contains a <text> node, because the gap between two spans is a rendered space, and it never rounds font-size past one decimal. And if you arrived looking for the other meaning of the phrase — describing something in words and getting a drawing back — that is text to SVG, which is a different job entirely.