50

I need to output multiple lines of text in SVG. For that I'm using the following scheme:

<text>
  <tspan> First line </tspan>
  <tspan> Second line </tspan>
</text>

First and second line of the text can have different number of characters, which can change dynamically. I want the second line to appear under the first line and text in both of them to be centered.

I can make second line appear below the first line by adding dy="15" for the second <tspan>.

I can align the text in each individual <tspan> by adding text-anchor="middle" to it.

But how to do relative centric alignment of those <tspan>'s?

I tried to use x="0" for each <tspan> but apparently it doesn't work since each <tspan> has different width and the rendered text in the shorter line is shifted to the left.

Is there a way to align centres of 2 <tspan>'s of different width using only CSS and/or SVG.

BartoNaz
  • 2,743
  • 2
  • 26
  • 42

3 Answers3

66

If you add text-anchor="middle" to each tspan you will center them (you have to remove the space between the tspans as well, otherwise the extra space will be considered as part of the first line and they won't be completely centered).

For example:

<svg>
    <text y="50" transform="translate(100)">
       <tspan x="0" text-anchor="middle">000012340000</tspan><tspan x="0" text-anchor="middle" dy="15">1234</tspan>
   </text>
</svg>

See: JSFiddle

helderdarocha
  • 23,209
  • 4
  • 50
  • 65
  • 2
    +1 because this answers the multiline portion of the question using `dy` as OP suggested. – jshanley Apr 24 '14 at 15:19
  • 2
    Thanks a lot. This resolved the problem. Funny enough, the space was really responsible for the misalignment of the lines. – BartoNaz Apr 24 '14 at 15:35
  • 2
    I think you forgot a point: `translate(100)`, where 100 is half the width of the svg, makes the base point is at center such that `x="0"` and `text-anchor="middle"` bring us the texts centered – Eric Nov 06 '17 at 11:39
  • Thanks @Eric. I was also looking for `transform="translate(100)"`, since `x` in the `tspan` overrides `x` in the `text`, and I wanted the `tspan`s placed relative to the `text`. – Gordon Jun 03 '21 at 20:55
41

DEMO

enter image description here

text-anchor='start' for right align.

text-anchor='middle' for middle align.

text-anchor='end' for left align.

Code from demo:

<svg width="100%" height="230" viewBox="0 0 120 230"
     xmlns="http://www.w3.org/2000/svg" version="1.1">

    <!-- Materialisation of anchors -->
    <path d="M60,15 L60,110 M30,40 L90,40 M30,75 L90,75 M30,110 L90,110" stroke="grey" />


    <!-- Anchors in action -->
    <text text-anchor="start"
          x="60" y="40">This text will align right</text>

    <text text-anchor="middle"
          x="60" y="75">This text will align middle</text>

    <text text-anchor="end"
          x="60" y="110">This text will align left</text>

    <!-- Materialisation of anchors -->
    <circle cx="60" cy="40" r="3" fill="red" />
    <circle cx="60" cy="75" r="3" fill="red" />
    <circle cx="60" cy="110" r="3" fill="red" />

<style><![CDATA[
text{
    font: bold 15px Verdana, Helvetica, Arial, sans-serif;
}
]]></style>
</svg>

Read more about text-anchor property here

Imran Bughio
  • 4,811
  • 2
  • 30
  • 53
  • 2
    The two tspan tags actually appear on the same line (and the demo doesn't use the given code example)… – Pierre Arlaud Nov 04 '15 at 14:35
  • Although the demo provided isn't really a direct answer to the question, I had to upvote it because the demo shows the other options to align the text. +1 for that. – Ricardo Zea Apr 07 '16 at 04:25
10

Key points to horizontally centering the text:
1. x="50%"
2. text-anchor='middle'

In your case, you may write as:

<svg style="width:100%">
  <text y="50">
    <tspan x="50%" text-anchor="middle"> First line </tspan>
    <tspan x="50%" dy="15" text-anchor="middle"> Second line </tspan>
  </text>
</svg>
Eric
  • 534
  • 5
  • 13
  • Key point is: svg isn't css, you're not centering the text within a box or something, think of `x="50%"` like a cursor, x must be centered, `ŧext-anchor="middle"` just define the text origin (that will be placed at x) – Alex Apr 24 '18 at 17:43