An SVG label with only an x value set usually lands somewhere you didn’t plan. Characters in SVG get placed by anchor points and painted with fill and stroke, and CSS boxes don’t come into it. They stay live and selectable the whole time, which is why chart labels and logos stay sharp at any size and curved headings don’t have to become pixels.
Wrapping is the documented gap. SVG 2 defines the inline-size property for it, yet the W3C SVG Working Group’s 23 April 2026 minutes record it as implemented in no browser (Inkscape does implement it), so line breaks fall to the author.
What Is SVG Text and How Is It Different From HTML Text?
Letters inside a vector-based SVG file stay character data. Searching and selecting them works, and scaling never turns them into pixels.
SVG 2 defines a small set of text content elements. The text element holds the string and sets its starting point. Inside it, tspan changes style or position partway through the string (it can also sit inside another tspan), and textPath lays the characters along a path referenced through href. The tref element from SVG 1.1 isn’t part of that set anymore.
Font handling matches HTML text, since both take their font from CSS font properties. According to the W3C SVG 2 specification, the text element behaves as a block while tspan and textPath behave as inline elements.
After that the two split apart. There’s no box model in SVG. MDN notes that the text element does not wrap by default, and the color comes from fill, because the color property is for HTML only.
Text is a graphics element like a rect or a path, so a gradient, pattern, clipping path, mask or filter applies to it as well.
The text element has been available across browsers since July 2015 (MDN compatibility data).
Characters placed in an SVG outside a text element aren’t rendered at all, and setting display won’t bring them back.
SVG fonts aren’t covered here. MDN’s SVG tutorial treats that format as separate from text display, so everything below assumes ordinary web fonts.
How to Position Text in an SVG
The x and y attributes set where the text baseline starts, not where its top-left corner sits.
Both take a length or a percentage, and both default to 0 (MDN).
Leave out y and the baseline lands on the top edge of the viewBox, so most of the line sits above the visible area.
One SVG 2 detail catches people out. x and y on text and tspan are not presentation attributes, so a CSS rule can’t set them (W3C SVG 2 specification, Chapter 11).
Offsetting and rotating single characters
dx and dy shift the current text position horizontally and vertically, and that’s how stacked lines get built. rotate turns each glyph by a number of degrees around its own position. All three accept lists, applied one value per character.
When a rotate list is shorter than the string, the last number rotates every remaining character. A dx or dy list just stops shifting once it runs out.
The limit is that dx, dy and rotate are ignored for auto-wrapped text (W3C SVG 2 specification). Pick one layout method per text block.
Scaling text with the viewBox
Text scales with the viewBox.
A text element is rendered like any other graphics element, so coordinate system transformations apply to it the same way they apply to shapes. Set font-size in user units and the label grows or shrinks with the graphic.
That’s proportional scaling, not typography that adapts to the screen. A 14-unit label on a chart squeezed into a narrow phone layout shrinks with everything else, and nothing lifts it back to a readable size.
For inline SVG, a CSS rule inside a narrow-screen media query can raise font-size on the label. For an SVG loaded as an image, the fix is a second file or a larger size in the source.
How to Center and Align SVG Text
Put x and y at the center point, then set text-anchor=”middle” for horizontal centering and dominant-baseline=”middle” or “central” for vertical centering.
Percentages are allowed in x and y (MDN), so x=”50%” and y=”50%” puts the anchor point in the middle of the SVG without any math.
Of all the dominant-baseline values, these are the ones that come up in practice.
| Value | Aligns the text to | Typical use |
|---|---|---|
| auto | Alphabetic baseline for horizontal text, central for vertical text | Default, no attribute needed |
| alphabetic | The font’s alphabetic baseline | Latin and other alphabetic scripts |
| middle | The middle baseline (alphabetic table checked first) | Vertical centering of Latin text |
| central | The central baseline (ideographic table checked first) | CJK or mixed-script text |
| hanging | The hanging baseline | Indic scripts |
text-anchor accepts start, middle and end, and start is the default (MDN). It works per text chunk, so on multi-line text every line gets aligned separately.
Each new absolute x or y value, including one on a tspan, starts a new chunk with its own anchor point. With direction set to rtl, start means the right edge.
dominant-baseline is defined in both the CSS Inline Layout Module Level 3 and SVG 2, and the CSS property wins over the attribute when both are set (MDN). It has been available across browsers since July 2020, so hand-tuned dy offsets are rarely needed now.
It does break with auto-wrapped text, though. text-anchor doesn’t apply to wrapped text outside an inline-size area, and that case needs text-align instead.
Vertical centering also depends on the font. When a font has no baseline table, or the table lacks the requested entry, the browser can fall back on heuristics (MDN), so a label that looks centered in one font sits slightly off in another. Test the real font, in more than one browser.
Styling SVG Text With Fonts, Fill and Stroke
Fonts come from the CSS Fonts Module, so font-family, font-size and font-weight work the way you’d expect. Painting is where SVG text differs. It uses fill and stroke where HTML would use color and border.
Set them as presentation attributes or with plain CSS. A CSS rule beats the matching attribute, which MDN states for text-anchor, dominant-baseline and paint-order.
Fill, stroke and gradients
Gradients and patterns work as text fills (MDN). The W3C SVG 2 specification adds a catch. With objectBoundingBox units, the bounding box is the whole text element, even when the gradient sits on a single tspan.
So a gradient meant for one word stretches across the entire line.
Strokes need a decision about order. By default the fill paints first and the stroke second, so the stroke draws over the letters.
paint-order=”stroke” flips that. MDN’s own example puts a white stroke under a crimson fill to keep the letters crisp, and the attribute has worked across browsers since January 2020.
Whatever pair you pick, check that there’s enough contrast between text and background colors.
Spacing and decoration
letter-spacing adds space between characters, and any non-default value turns discretionary ligatures off. word-spacing changes the gap at word boundaries. text-decoration covers underline, overline and line-through.
The ligature rule comes from the W3C SVG 2 specification. dx, textLength and the spacing attribute on textPath don’t break ligatures, and font-variant-ligatures switches the discretionary ones off if you’d rather not have them.
Why Custom Fonts Fail in SVG Text and How to Load Them
A custom font fails in SVG text when the SVG loads as an image, because browsers block external resources in that context.
As of MDN’s May 2025 revision of its SVG as an image guide, that covers the img element and CSS background-image. External images and stylesheets can’t load, which takes in web fonts, unless they’re inlined through data: URLs.
| Embedding method | External web fonts | Where @font-face lives |
|---|---|---|
| Inline SVG | Load | The page’s stylesheet |
| img or CSS background-image | Blocked | Inside the SVG, as a data URI |
| object, embed or iframe | Load | Inside the SVG file |
The last column follows from how @font-face works. The W3C WOFF2 Recommendation (8 August 2024) says linked fonts are only available to the documents that reference them.
When the file can go straight into the markup, SVG placed directly in the page is the easiest fix. The page’s @font-face rules and any Google Fonts stylesheet apply to the text just as they do to a heading.
If that isn’t possible, embed the font as a base64 data URI in a style block inside the SVG, or load the file through object, embed or iframe and declare @font-face inside it. Converting the text to outlines drops the font dependency entirely, with trade-offs covered further down.
For an SVG that has to load as an image, embed the font itself. The SVG 2 specification requires WOFF support so authors can ship the fonts their content needs, and notes that WOFF fonts can be compressed and subsetted.
WOFF2 goes further, with better compression than WOFF 1.0 and support in all major browsers per the W3C. Subset it to the characters the graphic uses, since base64 text is bulkier than the binary font, and then look at trimming SVG file size.
If the font still doesn’t load, the text falls back to the next family in font-family, and positions tuned for the original font go off. The W3C SVG 2 specification warns that x, y, dx and dy values written for a particular font can display with poor quality when that font isn’t available.
Does SVG Text Wrap Automatically?
Not reliably across browsers. SVG 2 adds inline-size for wrapping, but the April 2026 minutes record no browser implementing it, so manual tspan lines stay the portable choice.
| Method | Strength | Weak spot |
|---|---|---|
| tspan lines | Plain SVG 1.1 behavior | You break every line by hand |
| inline-size | One attribute, CSS-style wrapping | No browser implementation per April 2026 minutes |
| foreignObject | Full HTML and CSS text layout | The text is HTML, not SVG text |
Manual lines with tspan
Write one tspan per line, each with the same x and a dy of about one line height.
That’s the whole technique, and it works wherever SVG 1.1 text works.
It’s tedious, and it has real downsides. Nothing clips or shrinks a line that runs long, so a translated label can spill past the viewBox. Change the container width and every break needs redoing by hand.
SVG 2 also reads source line breaks when white-space is pre or pre-line, because SVG has no p or br element. That keeps the markup tidier. Test browser support before you rely on it.
inline-size in SVG 2
The SVG Working Group resolved on 23 April 2026 to keep inline-size as the simplest text wrapping method for SVG 2.
Its 5 March 2026 minutes went the other way for shapes. Wrapping text inside CSS shapes was dropped, because participants offered no commitment to implement it.
Status is limited. One member said inline-size is implemented in no browser, while another said Inkscape implements it and Firefox supports multi-line text in SVG.
A third suggested flagging it as at risk and removing it unless a second implementation appears.
The spec offers a hedge. Give the text and tspan elements x and y values as fallback lines: SVG 2 renderers ignore them for wrapped text, and renderers without wrapping draw them as manual lines.
Use inline-size as a bonus layer, never as the only line-breaking mechanism.
Wrapping with foreignObject
The foreignObject element hosts another XML namespace, and the W3C SVG 2 specification points to XHTML there for layouts SVG text can’t do, such as bulleted lists and tables.
Embedding HTML markup this way gives you real CSS wrapping, since the browser lays out an ordinary block.
You get reflow at any width, plus lists and tables. What you give up is SVG text itself, so text-anchor and textPath don’t apply, and any renderer that isn’t a browser has to understand the HTML inside. Test every place the file will open.
Fitting text to a width
textLength can squeeze or stretch a line to a target width, though that isn’t what it’s for.
The W3C SVG 2 text says the attribute is not intended for shrinking or expanding text, yet some tutorials present it as exactly that. Treat it as a calibration tool and resize with font-size. Honestly, font-size is the better tool anyway.
With lengthAdjust=”spacing”, the default, only the gaps between glyphs change. lengthAdjust=”spacingAndGlyphs” also stretches or compresses the glyphs along the text direction.
Browsers must hit the start and end positions, but where the glyphs in between land isn’t predictable.
And textLength does nothing when inline-size sets the wrapping area, or when white-space forces line breaks.
How to Put SVG Text on a Curve With textPath
Put a textPath element inside text, point its href at a path’s id, and the characters follow that path.
MDN’s example notes that the path is usually wrapped in defs so the guide line stays hidden, and it leaves that wrapper commented out so the red path stays visible.
The text starts at the path’s first point and runs in the direction the path was drawn, so draw the path the way you want the line to read.
If the curve is easier to sketch visually, a walkthrough for curving text in Figma covers the design-tool side.
Controlling start position and side
startOffset is the distance from the start of the path, as a length, percentage or number, and it defaults to 0. method is align by default, and stretch changes how glyphs are placed along the path. spacing takes exact (the default) or auto. side puts the text on the left (default) or right of the path direction.
Those defaults come from MDN’s textPath reference.
To center a line on the path, use startOffset=”50%” with text-anchor=”middle”. A percentage means distance along the entire path, and the midpoint of the string lands on that spot.
Mozilla’s own reftest confirms that a percentage startOffset ignores the pathLength attribute. Negative values and values past 100% are allowed too, which lets a line start off the path.
Stick to href. At the 23 April 2026 meeting a member reported the path attribute on textPath as not implemented at all, and the group kept it unchanged.
The side attribute is still in motion. The 5 March 2026 minutes record a Chromium implementation under way and a remark that Illustrator doesn’t plan to implement it, and the April meeting added IDL constants for it.
One more way this goes wrong: characters that run past the end of the path aren’t drawn there, so check that the path is long enough for the string.
Is SVG Text Accessible and Readable by Search Engines?
Yes, as long as the characters stay live text in the markup. Screen readers and crawlers can read character data, while the same SVG loaded as an image exposes only its alt text.
In inline SVG, text elements sit in the accessibility tree, so assistive tech and in-page search reach them.
In an img element, the content isn’t available to screen readers, so the alt attribute has to carry the meaning (EU data visualisation guide, data.europa.eu).
W3C’s SVG 2 specification describes SVG text as character data, which is why it can be selected, searched and magnified. It also recommends giving visible labels a semantic role.
Labeling takes ARIA labels plus the title and desc elements. The simplest version is role=”img” with an aria-label, one short name on the svg element. For fuller labels, title and desc go with aria-labelledby, and SVG-AAM calls linking to them redundantly the current best practice for fallback support. aria-labelledby on a group can also point at the id of a visible text element, so the label isn’t written twice.
More patterns for building accessible SVG files go beyond text labels.
There’s a catch with role=”img”. The img role excludes child content from the accessibility tree (SVG-AAM), so a chart wrapped in it exposes one name and none of its individual labels.
For data graphics, label the group instead and leave the text elements exposed.
SVG-AAM itself is a Working Draft dated 24 September 2026, and it warns that it’s an early draft with outdated information and errors. Browser behavior varies, so test with a real screen reader.
Contrast applies to SVG text like any other text. WCAG 2.2 success criterion 1.4.3 asks for at least 4.5:1 for normal text and 3:1 for large text (18 point, or 14 point bold).
WCAG’s key terms also cover strokes. A narrow outline counts as part of the letter, but a wide one that fills in the letter’s details acts as a halo and counts as background.
On search, the sources pull apart. The W3C SVG 2 specification says XML-aware search engines find SVG text strings with no extra work.
Google’s image SEO guide (updated March 2026) lists SVG among the formats supported in img src and says it doesn’t index CSS images. It points to alt text and the title element, and it doesn’t say that Google reads text inside the file.
So treat text inside the SVG as a bonus, and put the descriptive wording in alt text or the page copy.
Live Text or Outlines: Which Should You Use for SVG Text?
Choosing between live text and outlines
Keep text live when people read, search or translate it. Outline it when exact appearance outweighs all of that.
| Approach | Best for | Breaks when |
|---|---|---|
| Live text | Charts, labels, inline SVG, translated content | The font isn’t available where the SVG renders |
| Live text with embedded font | SVG that loads as an image and must stay selectable | The font isn’t subsetted and the file balloons |
| Outlined text | Logos, icons, files that must match everywhere | Someone needs to edit or translate the wording |
Live text can be selected and searched, and assistive tech can read it. Language swaps work through systemLanguage and the switch element, per the W3C SVG 2 specification. The downside is the font dependency, since a fallback font shifts every position.
Outlines go the other way. Figma’s developer docs say outlining guarantees the text looks exactly the same in the SVG as in the browser and in Figma. The cost is that the text loses its text properties and can’t be edited with text controls (Adobe Help, updated 22 April 2026), and it’s invisible to selection and screen readers until you add a label back.
Watch the defaults. Figma’s help center says SVG export writes text as glyphs by default, so an SVG exported from Figma carries no live text unless “Outline text” is unchecked.
If the graphic doesn’t need to stay vector, exporting the SVG to PNG also removes the font dependency, at the cost of sharp scaling.
How to convert SVG text to paths
| Tool | How it outlines text |
|---|---|
| Inkscape | Path menu, Object to Path (Shift+Ctrl+C), one path per letter inside a group |
| Adobe Illustrator | Type menu, Create Outlines (Outline text, Shift+Ctrl+O, in Illustrator on the web beta) |
| Figma | Export as SVG with Outline text checked, which is the default |
| opentype.js | Font.getPath(text, x, y, fontSize), then toPathData() or toSVG() |
- Lock the wording and keep an editable copy, because outlined text can’t be edited as text afterwards.
- Convert the text with one of the tools above.
- Check spacing and overlaps. opentype.js applies kerning by default but supports only the liga and rlig ligature features, and Inkscape’s per-letter split can leave glyph paths that overlap.
- Run SVGO (for example,
svgo logo.svg -o logo.min.svg) to strip the editor metadata, comments and hidden elements that vector editors leave behind. - Add the accessible name back with role=”img” and an aria-label, since outlines carry no characters.
SVG Text FAQ
How do you add text to an existing SVG file?
Open the file in a code editor and add a text element inside the svg root, with x and y values that fall within the viewBox. Put the string between the opening and closing tags, then set fill and font-size.
Why is my SVG text not showing?
A few things are worth checking. MDN notes that characters outside a text element never render. A missing y puts the baseline at 0, a fill that matches the background hides the glyphs, and a font that failed to load can change the look.
Can you animate SVG text?
Yes. MDN lists x, y, dx, dy, rotate and textLength as animatable, so SMIL animate elements work on them, and text takes CSS animations like any other graphics element.
How do you add a shadow to SVG text?
Apply a filter that contains an feDropShadow primitive to the text element. Filters apply to text the same way they apply to shapes, so one filter definition can serve several labels.
How do you put a background behind SVG text?
SVG text has no background property. Draw a rect behind it, sized from the text’s bounding box, which getBBox() returns in JavaScript. Fill the rect, then place the text element after it in the markup.
Can SVG text run vertically or right to left?
Yes. The SVG 2 specification supports vertical-rl and vertical-lr through the writing-mode property, and right-to-left and bidirectional text through direction. Arabic and Hebrew labels need no workaround.
Choosing How to Render SVG Text
SVG text should stay live unless the file loads through an img element or must look identical on every device. Live characters keep search, translation and screen reader support, and outlines remove all three.
Start with live, inline text. If the typeface fails, embed a subsetted WOFF2 font. Convert to outlines only as a last step.
The order matters because each step costs more than the one before. Embedding a font adds file weight, and outlining removes the text from the DOM for good.
Outlined files also need an aria-label added back by hand, which makes edits slower for every later revision. The advice changes if the SVG Working Group moves inline-size or the side attribute into broad browser support, so check the status in the W3C minutes before building around manual line breaks (verified 11 October 2026).
Once the lettering works, animating SVG with CSS is the natural next step.
- What is Backend in Web Development? - September 13, 2026
- What is Frontend Development? - September 11, 2026
- How to Make a Button in Figma: Design Best Practices - September 10, 2026


