52

Is it possible to display multiple lines of text in SVG without using the dy property? I'm using SVG 1.1 but might be able to use 1.2.

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <text x="0" y="15" font-size="15">
    <tspan>tspan line 1</tspan>
    <tspan>tspan line 2</tspan>
    <tspan>tspan line 3</tspan>
  </text>
</svg>

I've typed the code above. I want the text all flush to the left and each tspan to be a new line. Is tspan the only tag I can use? I want SVG to position the text lines vertically with line breaks. I do not want to manually enter the dy.

According to what I've read, each line should appear below the other. They are but they are also staggered across.

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <text x="0" y="0" font-size="15">
    <tspan dy="15">tspan line 1</tspan>
    <tspan dy="15">tspan line 2</tspan>
    <tspan dy="15">tspan line 3</tspan>
  </text>
</svg>

I guess it is required to add the x property. If you are setting the dy property to a fixed value, what happens when you change the font size?

This is working better than what I started with:

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xml:space="preserve">
  <text x="0" y="0" font-size="15" font-family="courier new" dy="0">
    <tspan x="0" dy="15">tspan line 1</tspan>
    <tspan x="0" dy="15">tspan line 2</tspan>
    <tspan x="0" dy="15">tspan line 3</tspan>
  </text>
</svg>

Is there a way to apply the x and dy to all the tspans? Maybe a property like line-height on the text element?

It doesn't look like the text tag has a property to set the delta y. It has been suggested in the comments to use JQuery to set the x attribute of all tspans. It looks like the dy property can accept other types of values such as points and percentages!? Is there a way to set the dy to a value that is 120% of the font size of its parent text element? I've tried to set it to 120%, but it doesn't seem to work like I expect. When I set 120% in the dy property, it goes off the screen. When I set it to 12 or 12px it stays in the same position. If I set it to 12%, it shifts slightly but is not 120% or 12px.

http://codepen.io/anon/pen/PqBRmd

It looks like it can accept any of the following:
http://www.w3.org/TR/SVG/types.html#InterfaceSVGLength

I've also looked up acceptable value types for dy and dx, and I can't make sense of it http://www.w3.org/TR/SVG/text.html#TSpanElementDXAttribute.

UPDATE 4:
Thanks for the answers so far. It looks like there is a way to display multiple lines of text spaced apart relatively. See my answer below.

Michael
  • 8,362
  • 6
  • 61
  • 88
1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231

3 Answers3

65

It looks like this will space the lines one after another without hard-coding a font size in each tspan. Font at 15px:

<svg style="border:1px solid black" >
    <text x="0" y="0" font-size="15" dy="0">
        <tspan x="0" dy=".6em">tspan line 1</tspan>
        <tspan x="0" dy="1.2em">tspan line 2</tspan>
        <tspan x="0" dy="1.2em">tspan line 3</tspan>
    </text>
</svg>

If you change the font size the lines continue to be spaced at 120% apart from each other or 1.2em. Font at 20px:

<svg style="border:1px solid black" >
    <text x="0" y="0" font-size="20" dy="0">
        <tspan x="0" dy=".6em">tspan line 1</tspan>
        <tspan x="0" dy="1.2em">tspan line 2</tspan>
        <tspan x="0" dy="1.2em">tspan line 3</tspan>
    </text>
</svg>

Example - http://codepen.io/anon/pen/oXMVqo

1.21 gigawatts
  • 16,517
  • 32
  • 123
  • 231
  • Technically the `x="0"` in the `` element is unnecessary, since you are setting `x` in all of the sub `` elements. One of the things I hate about how SVG does text is that you have to hard code the x position, and duplicate it for all the sub elements. – V. Rubinetti Oct 23 '19 at 13:35
5

just calculate the heights:

var drawx=part.x||0;
var drawy=part.y||0;
var fontSize=part.fontSize||14; 
var lineHeight=part.lineHeight||1.25; 
var style=part.style||""; 
var fontFamily=part.fontFamily||"Arial"; 
var text=part.text.split('\n').map(function(a,i){ return '<tspan x="'+drawx+'" y="'+(drawy+fontSize*lineHeight+i*fontSize*lineHeight)+'">'+a+'</tspan>' }).join('\n');

tqrSvg+='<text x="'+drawx+'" y="'+drawy+'" style="'+style+'" font-family="'+fontFamily+'" font-size="'+fontSize+'">'+text+'</text>'
Michael
  • 8,362
  • 6
  • 61
  • 88
Shimon Doodkin
  • 4,310
  • 34
  • 37
3

tspan is the right way to do it. And this is how:

<tspan x="10" dy="15">tspan line 1</tspan>

reference: http://tutorials.jenkov.com/svg/tspan-element.html

Reptar
  • 372
  • 1
  • 6
  • 20
  • 1
    Not sure why this is modded up. The very first sentence of the question: `without using the dy property` – Dan Jun 06 '22 at 11:41