Pure SVG way to fit text to a box

svg text/javascript
svg text rotate
svg rectangle with text
svg text wrap
react fit text to container
svg text center
svg circle with text
svg text width

Box size known. Text string length unknown. Fit text to box without ruining its aspect ratio.

After an evening of googling and reading the SVG spec, I'm pretty sure this isn't possible without javascript. The closest I could get was using the textLength and lengthAdjust text attributes, but that stretches the text along one axis only.

<svg width="436" height="180"
    style="border:solid 6px"
    xmlns="http://www.w3.org/2000/svg">
    <text y="50%" textLength="436" lengthAdjust="spacingAndGlyphs">UGLY TEXT</text>
</svg>

I am aware of SVG Scaling Text to fit container and fitting text into the box

I didn't find a way to do it directly without Javascript, but I found a JS quite easy solution, without for loops and without modify the font-size and fits well in all dimensions, that is, the text grows until the limit of the shortest side.

Basically, I use the transform property, calculating the right proportion between the desired size and the current one.

This is the code:

<?xml version="1.0" encoding="UTF-8" ?>
<svg version="1.2" viewBox="0 0 1000 1000" width="1000" height="1000" xmlns="http://www.w3.org/2000/svg" >
 <text id="t1" y="50" >MY UGLY TEXT</text>
 <script type="application/ecmascript"> 

    var width=500, height=500;

    var textNode = document.getElementById("t1");
    var bb = textNode.getBBox();
    var widthTransform = width / bb.width;
    var heightTransform = height / bb.height;
    var value = widthTransform < heightTransform ? widthTransform : heightTransform;
    textNode.setAttribute("transform", "matrix("+value+", 0, 0, "+value+", 0,0)");

 </script>
</svg>

Fitting Text Into a Box, The additional value would allow glyphs to be scaled both horizontally and vertically. (See: Pure SVG way to fit text to a box); An additional attribute '  Adding the <script> tag at the bottom of the root <svg> element causes it to execute after it's created the DOM structure above it, just like JavaScript on a web page. Thanks, I'm extremely impressed with your answer. Its much more work to accomplish this than I expected.

first of all: just saw that the answer doesn't precisely address your need - it might still be an option, so here we go:

you are rightly observing that svg doesn't support word-wrapping directly. however, you might benefit from foreignObject elements serving as a wrapper for xhtml fragments where word-wrapping is available.

have a look at this self-contained demo (available online):

<?xml version="1.0" encoding="utf-8"?>
<!-- SO: http://stackoverflow.com/questions/15430189/pure-svg-way-to-fit-text-to-a-box  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
   xmlns:xhtml="http://www.w3.org/1999/xhtml"
   xmlns:xlink="http://www.w3.org/1999/xlink"
   version="1.1"
   width="20cm" height="20cm"
   viewBox="0 0 500 500"
   preserveAspectRatio="xMinYMin"
   style="background-color:white; border: solid 1px black;"
>
  <title>simulated wrapping in svg</title>
  <desc>A foreignObject container</desc>

   <!-- Text-Elemente -->
   <foreignObject
      x="100" y="100" width="200" height="150"
      transform="translate(0,0)"
   >
      <xhtml:div style="display: table; height: 150px; overflow: hidden;">
         <xhtml:div style="display: table-cell; vertical-align: middle;">
            <xhtml:div style="color:black; text-align:center;">Demo test that is supposed to be word-wrapped somewhere along the line to show that it is indeed possible to simulate ordinary text containers in svg.</xhtml:div>
         </xhtml:div>
      </xhtml:div>
   </foreignObject>

  <rect x="100" y="100" width="200" height="150" fill="transparent" stroke="red" stroke-width="3"/>
</svg>

SVG text element, yourself, and break it into multiple lines. You can get some help from the relative positioning possible with the <tspan> element. Just use SVG. With width: 100% and a viewBox, SVG will be a fullsize box that resizes with an aspect ratio. Pretty neat trick! To set the type, you’ll need some magic numbers to get that viewBox just right and push the text into the right spot — but it’s doable with zero dependencies, just like the viewport units demo.

How to Stretch Text in Microsoft Word 2010, How do I stretch text to fill a text box? Embed Embed this gist in your website. Share Copy sharable link for this gist. Clone via HTTPS Clone with Git or checkout with SVN using the repository’s web address. Using Snap.svg to create a box with text in it. The bounding "container" box expands to fit the width of the text.

I dont think its the solution for what you want to do but you can use textlenght with percentage ="100%" for full width.

<svg width="436" height="180"
    style="border:solid 6px"
    xmlns="http://www.w3.org/2000/svg">
    <text x="0%" y="50%" textLength="100%">blabla</text>
</svg>

you can also add textanchor="middle" and change the x position to center perfectly your text

this will not change the fontsize and you will have weird space letterspacing...

JSFIDDLE DEMO

Fitting Text to a Container, to double its original width, for example, change the setting to 200 percent.  Select both the text and the guideline by holding down Shift and clicking on each one.  Or, you can click-and-drag a box around both of them. Put the text onto the guideline. Go to  Text > Put On Path.

SVG Text, How do I keep text in a box in HTML? The text will have a fixed size and when the circle is filled with text, the extra content should not be shown (like overflow hidden). The black circles with the text are really speech bubbles, which are meant to be printed and glued onto a poster. Do any of the fantastic SVG/Canvas libraries support

textLength, There are a number of ways to go about putting some text in a container and With width: 100% and a viewBox , SVG will be a fullsize box that  2. created a 2.75" x .75" paragrah text outline and centered to box 3. chose to align the p. text center/center 4. type my name scott 5. adjusted the font and size to way I want it 6. p. text fit path thing u showed me 7. then duplicated that box and text 8. change scott to another real long name

SVG alternative to fittext.js, see http://dabblet.com/gist/5231222 , Well organized and easy to understand Web building tutorials with lots of examples of how to use HTML, CSS, JavaScript, SQL, PHP, Python, Bootstrap, Java  Curve Text. Click Here to Read the Instructions (For Heaven’s sake, please take a minute to read the instructions) DesignBundles FREE SVG Files Free Design

Comments
  • I ended up making a loop in javascript that increases the font size until getBBox shows it would no longer fit. Ugly, so still hoping there would be some other way.
  • I have also been trying to get this same functionality to work. The best method I have found was the same one you did. Loop through JS and change font until it fits. But even in fonts there is still some whitespace above and below so you can't seem to get it just right.
  • This sucks, it seems like such a basic thing, but the spec is clear that it only stretches it in one direction. After playing around, I was able to get it close by modifying only the Y scale using transform, aka: transform="scale(0,5)" - jsfiddle.net/G5L8W
  • I am trying to think if there was a way to calculate the amount of scale being applied to the text on the x axis and apply it to the y axis, but that would then also mean adding in checks to make sure you aren't over scaling the Y, and then you're back at using JS. I'll bet you could use transform/scale with JS better though.
  • built-in support for this in SVG (or any text elements in a webpage) would be fantastic
  • Or simply... textNode.setAttribute("transform", "scale("+value+")");
  • Quick note- the scale attribute also affects the coordinate system of the current item, so if you want the element to be in the same position, will need to divide both x and y positions by the scalar to get the same relative position
  • Or even more simply... set the text font-size to 1 (1em in our case); then once you have the scale factor (value in this answer) just set the font-size to it. See example below.
  • I also wanted the text to be verticaly-centered, so I changed the end (after var value = ...) to textNode.style.transform = "translateY(50%) scale(" + value + ")"; textNode.style.transformOrigin = '0px 0px'; textNode.style.dominantBaseline = 'central';
  • I am converting an svg to png using imagemagick and as I thought, this js is not working there. Is there any recommendation to get it work when I am converting SVG to PNG?
  • Thanks, but was not interested in word wrapping.
  • @collapsar, your demo link is broken
  • It yust expands the letter spacing. :(
  • Yep, and just to be clear on the text centering - the attribute is "text-anchor" and you would need also x=50% like <text x="50%" y="50%" textLength="100%" text-anchor="middle">AB</text>