How To Reuse SVG Text With The tref Element

Writing SVG code once and being able to use it in multiple places helps you write more modular code and it helps make maintenance easier. SVG makes it easy to reuse text through the tref element.

Last week I walked you through the tspan element and showed how you could use it to style and position lines of text independent from one another. I presented some examples using the positioning attributes x, y, dx, and dy and mentioned there were a couple more attributes to look at.

Let’s pick things up with the two remaining attributes and then I’ll talk about reusing SVG text with the tref element. Please note that while the tref element is part of the SVG 1.1 spec, it’s being removed from the SVG 2.0 spec. I included in this series, in case you run across it somewhere.

The textLength and lengthAdjust Attributes

The two remaining attributes are textLength and lengthAdjust, and either or both can be added directly to any tspan.

As I’ve done with most of the examples in this series. I created an SVG element, defined the size of the viewport, and styled it so we can see an outline of the viewport and any text that renders outside of it. I also bumped up the font-size.

1
2
3
4
5
6
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text textLength="400" lengthAdjust="spacingAndGlyphs">  
    <tspan x="280" y="80">SVG 1</tspan>  
    <tspan x="280" dy="36" fill="red">SVG 2</tspan>  
  </text>  
</svg>

I positioned the two tspans so one sits below the other and styled the second with a red fill. I also added both textLength and lengthAdjust attributes to the <text> element. The text isn’t stretched as you might expect.

SVG 1SVG 2

However, adding the attributes to the first tspan does what you would expect. It stretches both the space and glyphs as the next example shows.

1
2
3
4
5
6
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="280" y="40">  
    <tspan x="280" y="80" textLength="400" lengthAdjust="spacingAndGlyphs">SVG 1</tspan>  
    <tspan x="280" dy="36" fill="red">SVG 2</tspan>  
  </text>  
</svg>

SVG 1SVG 2

This suggests that unlike the rotate attribute, which we saw last week, textLength and lengthAdjust set on the text element don’t propagate to the tspans.

One exception I found while playing around is if you add the textLength and/or lengthAdjust to the text element and haven’t set x and y values for the first tspan, the textLength and lengthAdjust do seem to propagate.

I’m not sure if this is an error or the intended behavior, but I wanted to mention it in case it happens and you’re wondering why.

1
2
3
4
5
6
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <text x="280" y="80" textLength="400" lengthAdjust="spacingAndGlyphs">hello  
    <tspan>SVG 1</tspan>  
    <tspan x="280" dy="36" fill="red">SVG 2</tspan>  
  </text>  
</svg>

In this example I added the text “hello” directly to the text element and before the first tspan and I added our two attributes directly on the text element. I also positioned the text element and since I didn’t give any x or y coordinate to the first tspan it gets positioned just after the “hello” text.

The word “hello” is stretched as you would expect, but so is the SVG 1 text from the first tspan. It seems setting textLength and lengthAdjust stretch the line they’re applied to regardless of which element they’re set on.

helloSVG 1SVG 2

If you take away the coordinates on the second tspan, it will also become part of the stretched line of SVG text.

helloSVG 1SVG 2

Again I’m not sure if this is the expected behavior, a bug, or if I’m doing something wrong, but I thought I’d point it out in case you run across it.

The tref Element

Note: The tref element is part of the SVG 1.1 spec, but it’s being removed from the SVG 2.0 spec. What follows may or not work by the time you read this. I’ll be using images to show the results of the examples.

Earlier in the year during the previous round of this SVG series I showed how you could define SVG code in one location and then use and reuse it in other parts of your SVG document.

The tref element works the same way. It lets you define reference text inside a <defs> element and then reference it later. I’ll refer you back to my post about <defs> if you need a reminder about how this works.

Or you can just follow along with the example in which I created a <text> element with SVG 1 inside and then I wrapped the <text> element with <defs> tags. Notice that I added an id of “referenced” to the <text> element.

To reference the text you use the xlink:href attribute inside a <tref> element where you want the text to appear.

1
2
3
4
5
6
7
8
9
10
11
12
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <defs>  
    <text id="referenced">SVG</text>  
  </defs>

  <text>  
    <tspan x="280" y="80">  
      <tref xlink:href="#referenced"/>  
    </tspan>  
    <tspan x="280" dy="36" fill="red">SVG 2</tspan>  
  </text>  
</svg>

Here I referenced the SVG 1 text inside a tref element while SVG 2 is inside a tspan that I’ve positioned beneath SVG 1.

SVG tref

I could be more efficient and set the defs to contain the text SVG and reference it in both tspans adding the 1 or 2 at the end.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<svg width="660" height="220" style="outline: 1px solid red; font-size: 2em; overflow: visible;">  
  <defs>  
    <text id="referenced-2">SVG</text>  
  </defs>

  <text>  
    <tspan x="280" y="80">  
      <tref xlink:href="#referenced-2"/> 1  
    </tspan>  
    <tspan x="280" dy="36" fill="red">  
      <tref xlink:href="#referenced-2"/> 2  
    </tspan>  
  </text>  
</svg>

Here I added the 1 and 2 on each tspan, but have the SVG text as a reference inside trefs in each. I also changed the id to referenced–2 so that it doesn’t conflict with the previous example.

SVG tref

In these examples I placed the tref inside tspans, but the tref could also have been placed directly inside the text element. The referenced text will appear wherever the tref is added.

Closing Thoughts

If you understand how to work with <defs> and how to generally reuse SVG code, I’m guessing you won’t have any problems working with the <tref> element either as it works the same way.

You define the text you want to reuse inside <defs> tags and then reference the text inside a <tref> element using the xlink:href attribute. It’s more complicated to explain that to use.

There’s still plenty more to cover in regards to SVG text. Over the next two week I’ll talk about text layout features that are supported by SVG and show you some properties to help align SVG text in both the horizontal and vertical directions.

Download a free sample from my book, Design Fundamentals.

Leave a Reply

Your email address will not be published. Required fields are marked *