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

AttributeWhat it does
x, yPosition of the anchor point, on the baseline
dx, dyShift from where the text would otherwise be
text-anchorstart, middle or end: which part of the text sits at x
dominant-baselineWhich line of the lettering sits at y: auto, middle, central, hanging
font-familyFont names, in order of preference
font-sizeSize of the lettering, in the drawing’s units
font-weight, font-stylebold, italic and so on
letter-spacingExtra space between letters
fill, strokeColour of the letters and of their outline
textLengthSqueezes or stretches the text to an exact length
transformRotates 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:

ValueResult
start (the default)Text begins at x and runs right
middleText is centred on x
endText 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 seeCauseFix
No text at ally is 0, so the text is above the drawingSet y to the font size or more
No text at allThe fill matches the background, or is noneSet fill
Tiny or huge textFont size is in viewBox unitsScale font-size to the viewBox
A different font on another computerThe font is not installed thereConvert the text to paths, or use a generic family
Text runs off the edgeSVG text does not wrapBreak it into <tspan> lines, or use textLength
text-align: center does nothingIt does not apply to SVG texttext-anchor="middle"
Text missing after uploading to a cutting programEditable text is not supportedConvert the text to paths
Vertical centring is off in an editordominant-baseline is not supported thereUse 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.