htmlcsssvg

How do you translate an SVG element by a percentage of it's own size?


I'm trying to make a dynamically generated SVG that displays some data from an API endpoint. If the response text is too long, the text becomes an infinitely scrolling marquee via CSS animations. However, I'm running into the problem that transformX(100%) for a <text> element inside the SVG isn't 100% of the size of the text, but the parent element instead (see: here), which means the animation doesn't scale properly with length. Is there some way I can loop an animation based on the size of the text element instead? :(

Some styling in animatedTitle:

.title {
  animation-name: overflow-scroll;
  animation-duration: 10s;
  animation-iteration-count: infinite;
  animation-timing-function: linear;
  max-width: none;
}
@keyframes overflow-scroll{
  0% { transform: translateX(0); }
  100% { transform: translateX(-100%); }
}

Generating the SVG:

<svg>
  <defs>
    <style>
      { titleData.length > 22 ? animatedTitle : "" }
    <style>
  <defs>

  <text x="80" y="37" className="title" {...titleStyle}>
    <tspan>{titleData}</tspan>
    { titleData.length > 22 && <tspan>{titleData}</tspan>}
  </text>
</svg>

Solution

  • Modern browsers support the CSS property transform-box. You can play with that to do the trick

    .title {
      transform-box: fill-box;
      transform-origin: 0 50%;
      animation: overflow-scroll 10s linear infinite;
    }
    
    @keyframes overflow-scroll {
      0%   { transform: translateX(0); }
      100% { transform: translateX(-100%); }
    }
    
    <svg>
      <text x="80" y="37" class="title">
        <tspan>…your text…</tspan>
        <tspan>…your text…</tspan>
      </text>
    </svg>