Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using textLength attribute

Tags:

svg

I have segments of text that I want to put into a fixed 80px width, and I'm looking for the best way to implement fall-back if they don't quite fit (they will all be very close so I expect spacing can be used to make corrections).

I looked at the documentation for the textLength attribute but found it very hard to understand -- and the examples don't help at all. Specifying the pixel width on a text element garbles the text in Firefox and does nothing in my Chrome.

An article at More Robust SVG Text gave examples in 'em' units, but I haven't found any official documentation to explain why that works when pixels do not. Using that method helps in Firefox (although it's ignored on tspan), but is totally ignored in Chrome.

<svg width="570px" height="310px" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
text {
    text-anchor: middle;
    font-size: 13px;
    font-weight: bold;
    font-family: "Times New Roman";
}
</style>

<rect  x="115" y="180" width="80"  height="80" fill="white" stroke="black"/>
<text x="155" y="180"  textLength="80">
<tspan dy="1.2em" x="155" >Elizabeth</tspan>
<tspan dy="1.1em" x="155" >Taylor</tspan>
<tspan dy="1.1em" x="155" >(c1731&#x2013;1783)</tspan>
</text>
</svg>

Can someone explain how to use it in a portable way?

like image 955
ACProctor Avatar asked Feb 11 '26 13:02

ACProctor


1 Answers

The problem is that the behaviour of textLength when there are <tspan> elements is a little buggy on all(?) browsers.

Firefox's behaviour is correct I think, and makes sense if you leave all the <tspan> elements in their default position, and don't move them.

(View this in Firefox)

<svg width="570px" height="310px" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
text {
    text-anchor: middle;
    font-size: 13px;
    font-weight: bold;
    font-family: "Times New Roman";
}
</style>

<rect  x="115" y="180" width="80"  height="80" fill="white" stroke="black"/>
<text x="155" y="180" textLength="80">
<tspan dy="1.2em" x="155" >Elizabeth</tspan>
<tspan dy="1.1em" x="155" >Taylor</tspan>
<tspan dy="1.1em" x="155">(c1731&#x2013;1783)</tspan>
</text>

<text x="155" y="180" textLength="80">
<tspan>Elizabeth</tspan>
<tspan>Taylor</tspan>
<tspan>(c1731&#x2013;1783)</tspan>
</text>
</svg>

It is resizing all the text so that its total length is 80px.

Perhaps you wanted each <tspan> to be length 80px? You don't say. The reason that isn't happening is because textLength is not a style property. Thus it isn't inherited by the <tspan> elements. If you want that, you have to set that attribute on every <tspan>.

<svg width="570px" height="310px" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
text {
    text-anchor: middle;
    font-size: 13px;
    font-weight: bold;
    font-family: "Times New Roman";
}
</style>

<rect  x="115" y="180" width="80"  height="80" fill="white" stroke="black"/>
<text x="155" y="180">
<tspan dy="1.2em" x="155" textLength="80">Elizabeth</tspan>
<tspan dy="1.1em" x="155" textLength="80">Taylor</tspan>
<tspan dy="1.1em" x="155" textLength="80">(c1731&#x2013;1783)</tspan>
</text>
</svg>

Unfortunately, this only works on Chrome currently, but not on Firefox.

Basically it seems that Chrome only likes textLength when it is on a leaf child element. And Firefox only likes it when it is on a parent text element.

You don't say exactly what you want, but my recommendation would be to avoid <tspan> and use proper <text> elements for every line, if you want the behaviour to match on all browsers.

(The following example looks the same on Chrome and Firefox)

<svg width="570px" height="310px" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<style>
text {
    text-anchor: middle;
    font-size: 13px;
    font-weight: bold;
    font-family: "Times New Roman";
}
</style>

<rect  x="115" y="180" width="80"  height="80" fill="white" stroke="black"/>
<text x="155" y="180" dy="1.2em" textLength="80">Elizabeth</text>
<text x="155" y="180" dy="2.3em" textLength="80">Taylor</text>
<text x="155" y="180" dy="3.4em" textLength="80">(c1731&#x2013;1783)</text>
</svg>
like image 188
Paul LeBeau Avatar answered Feb 14 '26 09:02

Paul LeBeau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!