skip to Main Content

I’ve been trying to vertically align a tspan inside a span in SVG for a few hours now, with no success.

I’ve also tried using some suggestions from stackoverflow answers and questions with reference to dominant-baseline="middle" and alignment-baseline="middle", but nothing happened.

What I have currently done after some trial and error is this code here:

<svg xmlns="http://www.w3.org/2000/svg" width="200" height="66"
  style="position: absolute; left: 0px; top: 0px; user-select: none;">
    <rect width="200" height="66" x="0" y="0" fill="cyan"></rect>
    <g>
        <text class="t" x="30" y="30" xlink:space="preserve"
      style="font-size: 10px; font-family: monospace" fill="black"
      dominant-baseline="middle" alignment-baseline="middle">ISTRUE:
      <tspan class="tt" dominant-baseline="central" alignment-baseline="middle"
      fill="green" style="font-size: 20px;">YES</tspan></text>
    </g>
</svg>

At the end "ISTRUE:" class="t" has to be vertical aligned with "YES" class="tt" inside class="t".

They have a different font size and may also have a different family-font (for now it’s monospace for both of them)

2

Answers


  1. If you add x and y values ​​to the tt class, it can be aligned vertically. You can see it in the code below. You can edit the spaces as you wish.

    <svg xmlns="http://www.w3.org/2000/svg" width="200" height="66"
      style="position: absolute; left: 0px; top: 0px; user-select: none;">
        <rect width="200" height="66" x="0" y="0" fill="cyan"></rect>
        <g>
            <text class="t" x="30" y="30" xlink:space="preserve"
          style="font-size: 10px; font-family: monospace" fill="black"
          dominant-baseline="middle" alignment-baseline="middle">ISTRUE:
          <tspan class="tt" x="30" y="50" dominant-baseline="central" alignment-baseline="middle"
          fill="green" style="font-size: 20px;">YES</tspan></text>
        </g>
    </svg>
    Login or Signup to reply.
  2. You can do without any x y positioning, by animating the text over a path

    • visibility code to prevent a FOUC
    • animateMotion set `to dur=".001s" to display "immediatly"
      (text is displayed at 0,0 first)
    • keypoints="0.5,0.5" to animate to halfway the path
    • to be precise: the <g> is animated, not the <text>
    • set the path stroke to transparent to hide it
      or rename the attribute stroke to no-stroke (not a SVG attribute!)
    <svg width="400" viewBox="0 0 200 66" style="background:cyan">
      <style>
        .true { font:15px monospace; fill:black }
        .yes  { font:30px Arial;     fill:green }
      </style>
      <path id="guide" d="M40 0v66" stroke="red"/>
      <path d="M0 33h200" stroke="blue"/>
      <g dominant-baseline="central" visibility="hidden">
        <set attributeName="visibility" from="hidden" to="visible" begin=".01s" />    
        <animateMotion dur=".001s" fill="freeze" keyPoints=".5;.5" keyTimes="0;1" calcMode="linear">
          <mpath href="#guide"/>
        </animateMotion>
        <text class="true">ISTRUE:</text>
        <text class="yes" dx="2em">YES</text>
      </g>
    </svg>

    Note

    Because that id="guide" is a global ID
    You are going to run into trouble when you add multiple SVGs to the page.
    That first ID will always be used by all SVGs using that guide.

    Easily avoided by wrapping your SVG in declarative shadowDOM
    side-effect: now global CSS can not style the SVG
    <svg-protected> can be any name you want (with a hyphen!)

    <svg-protected>
      <template shadowrootmode="open">
        <svg width="300" viewBox="0 0 200 66" style="background:gold">
          <style>
            .true{font:15px monospace;fill:black} .yes{font:30px Arial;fill:green}
          </style>
          <path id="guide" d="M40 0v66" stroke="red"/>
          <g dominant-baseline="central" visibility="hidden">
            <set attributeName="visibility" from="hidden" to="visible" begin=".01s" />    
            <animateMotion dur=".001s" fill="freeze" keyPoints=".5;.5" keyTimes="0;1" calcMode="linear">
              <mpath href="#guide"/>
            </animateMotion>
            <text class="true">ISTRUE:</text><text class="yes" dx="2em">YES</text>
          </g>
        </svg>
      </template>  
    </svg-protected>
    <svg-protected>
      <template shadowrootmode="open">
        <svg width="300" viewBox="0 0 200 66" style="background:beige">
          <style>
            .true{font:15px monospace;fill:red} .yes{font:30px Arial;fill:gold }
          </style>
          <path id="guide" d="M60 0v66" stroke="red"/>
          <g dominant-baseline="central" visibility="hidden">
            <set attributeName="visibility" from="hidden" to="visible" begin=".01s" />    
            <animateMotion dur=".001s" fill="freeze" keyPoints=".5;.5" keyTimes="0;1" calcMode="linear">
              <mpath href="#guide"/>
            </animateMotion>
            <text class="true">ISTRUE:</text><text class="yes" dx="2em">YES</text>
          </g>
        </svg>
      </template>  
    </svg-protected>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search