1

I am writing/animating multiline SVG text using the tspan selector. Unfortunately every line (besides the first) has the beginning letters crammed towards the front. I have tried letter spacing and kearning, neither of which has helped. I need to use y and dy to establish vertical placement, but unfortunately that's what seems to be causing the issue. StartOffset was useless. Hoping someone might know the answer! See picture below and link to codepen [here

<div id="wavytext">
  <h3>
  <svg viewBox="50 -50 3000 550">
  <path id="wave" d="M42.23,158.8C80.53,105.3,247.77,34.91,435.85,37.17c254,3,482.6,135.07,662.23,133.46,250-2.26,351.39-72.65,405.45-152" 
        />
    
   <text id="textwave" x="100" y="25"
          dominant-baseline="central">
         <textPath id="textpath" href="#wave">  
           
  <a href="https://www.breakpointbranding.com/services">
     <tspan id="webdesign" x="15" y="50">+ CUSTOM WEBSITE DESIGN
  <animate attributeName="x"
               from="5%" to ="90%"
               begin="webdesign.mouseover" dur="10s"
               repeatCount="0" id="go"
               end="webdesign.mouseout" dur="7.5s" 
               repeatCount="0" id="go"/>
         </tspan></a>
           
            <a href="https://www.breakpointbranding.com/services">
     <tspan id="social" x="50" dy="2em">+ SOCIAL MEDIA MANAGEMENT
  <animate attributeName="x"
               from="10%" to ="90%"
               begin="social.mouseover" dur="10s"
               repeatCount="0" id="go"
               end="social.mouseout" dur="7.5s" 
               repeatCount="0" id="go"/>
         </tspan></a>
           
           <a href="https://www.breakpointbranding.com/services">
     <tspan id="designday" x="50" dy="2em">+ DESIGN DAY EXCLUSIVE
  <animate attributeName="x"
               from="12%" to ="90%"
               begin="designday.mouseover" dur="10s"
               repeatCount="0" id="go"
               end="designday.mouseout" dur="7.5s" 
               repeatCount="0" id="go"/>
         </tspan></a>
           
    </text>
  </svg>
    </h3>
</div>

stacked SVG text tspan crunched

Hoping someone can assist in evenly spacing apart the letters of the SVG text on lines 2 and 3.

Devon
  • 11
  • 1

1 Answers1

0

You are triggering buggy text layout by combining tspan and textPath. Get rid of the tspans and separate out your three text segments into three separately positioned text elements using transforms. Use (and animate) startOffset in the textPath for animation.

Here is a version that does not trigger buggy layout - start from here I'd advise.

h3 {
  font-family: 'Lato' !important;
  font-size: 4.6rem !important;
font-kerning: inherit;
}


#wave {
  stroke-width: 4%;
  fill:transparent;
}

.textwave {
  fill: #DAFF60 !important; /* Will override color (regardless of order) */
  stroke-width: 3px !important;
  stroke: #4E71F2 !important;
}
<div id="wavytext">
  <h3>
  <svg viewBox="50 -50 3000 650">
  <path id="wave" d="M42.23,158.8C80.53,105.3,247.77,34.91,435.85,37.17c254,3,482.6,135.07,662.23,133.46,250-2.26,351.39-72.65,405.45-152" 
        />
    
   <text id="webdesign" class="textwave" x="100" y="25">
         <textPath id="textpath1" href="#wave" startOffset="0%">  
           <animate attributeName="startOffset"
               from="5%" to="90%"
               begin="webdesign.mouseover" dur="10s"
               end="webdesign.mouseout" dur="7.5s" />
  <a href="https://www.breakpointbranding.com/services">
    + CUSTOM WEBSITE DESIGN</a>
           </textPath>
           </text>
           
<text id="designday" class="textwave"" x="100" y="425" transform="translate(0,400)">
         <textPath id="textpath2" href="#wave" startOffset="0%">  
           <animate attributeName="startOffset"
               from="5%" to ="90%"
               begin="designday.mouseover" dur="10s"
               repeatCount="0" id="go"
               end="designday.mouseout" dur="7.5s" 
               repeatCount="0" id="go"/>
  <a href="https://www.breakpointbranding.com/services">
    + SOCIAL MEDIA MANAGEMENT</a>
           </textPath>
           </text>           
           
<text id="socialmedia" class="textwave" x="100" y="425"
          dominant-baseline="central" transform="translate(0,200)">
         <textPath id="textpath3" href="#wave" startOffset="0%">  
           <animate attributeName="startOffset"
               from="5%" to ="90%"
               begin="socialmedia.mouseover" dur="10s"
               repeatCount="0" id="go"
               end="socialmedia.mouseout" dur="7.5s" 
               repeatCount="0" id="go"/>
  <a href="https://www.breakpointbranding.com/services">
    + DESIGN DAY EXCLUSIVE</a>
           </textPath>
           </text>                 
  </svg>
  </h3>
</div>
Michael Mullany
  • 30,283
  • 6
  • 81
  • 105
  • Michael this is amazing!!! One question though- for some reason my CSS isn't overriding the black fill text on the class, despite the important tag. BTW, this is similar to the first version I had, and found the tspan element to be a cleaner/more organized solution. Do tspans always behave this way? Or is there a transform property I can add to the tspan to avoid the letter crunch? I'm just curious as to "why" it's happening (in layman's terms lol). – Devon Mar 02 '23 at 16:33
  • Note- the fill and stroke were being determined by 1. the link property (a) which I then set to "undefined" 2. the fact that we had used the h3 tag, which I removed from the html, and correspondingly changed to "body" in the css, which gave me much more control over the font size and other options :-) – Devon Mar 02 '23 at 19:01
  • The "why" is that there are a lot of bugs in SVG text handling - you really have to test anything fancy you do with SVG text cross-browser : ) – Michael Mullany Mar 02 '23 at 20:21