SVG text: position, size, anchor, fonts and wrapping
How the SVG text element works: x and y set the baseline, text-anchor aligns it, font-size scales with the viewBox, and lines are wrapped by hand with tspan.
Published
Text in an SVG is written with the <text> element. Its x and y attributes place the start of the text’s baseline, font-size and font-family set the lettering, text-anchor aligns it to the left, centre or right of that point, and fill colours it. SVG text does not wrap on its own: each line is positioned by hand.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 60">
<text x="100" y="38" font-family="Georgia, serif" font-size="24" text-anchor="middle" fill="navy">Hello, world</text>
</svg>
The attributes
| Attribute | What it does |
|---|---|
x, y | Position of the anchor point, on the baseline |
dx, dy | Shift from where the text would otherwise be |
text-anchor | start, middle or end: which part of the text sits at x |
dominant-baseline | Which line of the lettering sits at y: auto, middle, central, hanging |
font-family | Font names, in order of preference |
font-size | Size of the lettering, in the drawing’s units |
font-weight, font-style | bold, italic and so on |
letter-spacing | Extra space between letters |
fill, stroke | Colour of the letters and of their outline |
textLength | Squeezes or stretches the text to an exact length |
transform | Rotates or moves the text, as for any shape |
All but x, y, dx, dy and textLength can also be set in CSS.
Position: y is the baseline
The most common surprise is that y is not the top of the text. It is the baseline, the line the letters stand on. Text placed at y="0" therefore sits above the top edge of the drawing, and little or nothing shows. Set y to at least the font size, or use dominant-baseline="hanging", which hangs the text below the point.
Alignment: text-anchor
The CSS text-align property has no effect on SVG text. text-anchor does the job, relative to the x position:
| Value | Result |
|---|---|
start (the default) | Text begins at x and runs right |
middle | Text is centred on x |
end | Text ends at x |
The value is inherited, so it can be set once on a group.
Centring text in a shape
To centre text across the drawing, put x in the middle and anchor the middle. To centre it vertically as well, move the baseline:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 80">
<rect width="200" height="80" fill="gold"/>
<text x="50%" y="50%" text-anchor="middle" dominant-baseline="central" font-size="20">Centred</text>
</svg>
Percentages for x and y are measured against the viewBox. Browsers support dominant-baseline, but some other software ignores it. The portable alternative is to leave it out and nudge the text down with dy="0.35em", about half the height of a capital letter.
Size
font-size="24" means 24 of the drawing’s units, not 24 pixels. Like everything else in the SVG it scales with the viewBox: in a viewBox 200 units wide shown at 400 pixels, that text is drawn at 48 pixels. If the text in an SVG looks tiny or enormous, compare the font size with the viewBox numbers before anything else.
Wrapping and line breaks
A <text> element is a single line. A line break typed into it is treated as a space. For several lines, wrap each in a <tspan>, send it back to the left edge with x, and step down with dy:
<text x="10" y="30" font-size="16">
<tspan x="10" dy="0">First line</tspan>
<tspan x="10" dy="1.2em">Second line</tspan>
<tspan x="10" dy="1.2em">Third line</tspan>
</text>
Where each line ends is your decision: nothing measures the text against a width and breaks it for you. Newer versions of the SVG standard describe automatic wrapping, but browsers have not taken it up. For text that must reflow in a web page, put HTML beside or over the SVG. <foreignObject> can place HTML inside the SVG and works in browsers, but not in most other software that reads SVG.
<tspan> is also how to style part of a line, for example one word in bold or another colour.
To make a label fit a fixed width, textLength="180" spaces the letters out or in until the text is exactly 180 units long. Add lengthAdjust="spacingAndGlyphs" to stretch the letters as well as the gaps.
Text along a curve
Text can follow any path:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 100">
<path id="curve" d="M 20 80 Q 100 10 180 80" fill="none"/>
<text font-size="14">
<textPath href="#curve" startOffset="50%" text-anchor="middle">Text on a curve</textPath>
</text>
</svg>
startOffset="50%" with text-anchor="middle" centres the words on the curve.
Fonts
An SVG does not carry its fonts. It names them, and the program showing the file uses its own copy. If the font is missing, another is substituted and the layout shifts.
- Inline in a web page, SVG text uses the page’s fonts, web fonts included.
- In an
<img>tag or a CSS background, the SVG cannot load outside files, so only fonts installed on the visitor’s device work, unless the font is embedded in the SVG file itself as a data URI. - In other software, only fonts installed on that computer work.
The safe choices are the generic families serif, sans-serif and monospace, which always resolve to something, or converting the text to outlines.
Converting text to paths
Converting replaces each letter with a shape. The file then looks the same everywhere and needs no font, at the cost that the words can no longer be edited, selected or read by a search engine.
It is the safe course for any cutting machine, and Cricut Design Space requires it. Design Space does not accept editable text in an SVG: text has to be turned into shapes before the file is uploaded. In Inkscape, select the text and use Path, Object to Path. In Illustrator, use Type, Create Outlines. With a script font whose letters overlap, also unite the letters into one shape, so that the machine does not cut each letter apart from its neighbour. How to upload an SVG to Cricut Design Space lists the other things a file must avoid.
The SVG viewer counts the text elements in a file and warns when it finds any.
Outlined text
Text takes stroke like any shape. A stroke is centred on the edge of each letter, so a thick one eats into the letter. paint-order="stroke" paints the stroke behind the fill and keeps the letters at full weight:
<text x="10" y="40" font-size="32" font-weight="bold" fill="white" stroke="black" stroke-width="4" paint-order="stroke">Outline</text>
Common problems
| What you see | Cause | Fix |
|---|---|---|
| No text at all | y is 0, so the text is above the drawing | Set y to the font size or more |
| No text at all | The fill matches the background, or is none | Set fill |
| Tiny or huge text | Font size is in viewBox units | Scale font-size to the viewBox |
| A different font on another computer | The font is not installed there | Convert the text to paths, or use a generic family |
| Text runs off the edge | SVG text does not wrap | Break it into <tspan> lines, or use textLength |
text-align: center does nothing | It does not apply to SVG text | text-anchor="middle" |
| Text missing after uploading to a cutting program | Editable text is not supported | Convert the text to paths |
| Vertical centring is off in an editor | dominant-baseline is not supported there | Use dy="0.35em" |
Questions
Is SVG text real text? Yes. Inline in a page it can be selected, copied, searched and read by screen readers.
Can SVG text have a gradient or a pattern? Yes. fill="url(#id)" works as for any shape: see fill and stroke.
How do I rotate text? With transform="rotate(-90 x y)", giving the text’s own x and y as the centre of rotation.