skip to Main Content

I have an SVG on a HTML page that has a dynamic width, and I want to draw a circular text path within it that will stay centred no matter how the browser window is resized.

<style>
#mysvg {
float: left;
position: fixed;
top: 0;
left: 0; }
</style>

<svg id="mysvg" width="100%" height="100%">
  <rect x="0" y="0" width="100%" height="100%" fill="white" />
  <circle id="svg_circle" cx="50%" cy="50%" r="360" fill="none" />
  <text id="svg_text" fill="black">
    <textPath xlink:href="#svg_circle">my text</textPath>
  </text>
</svg>

I don’t want the circle to scale so viewBox is inappropriate. However, the background should fill the browser window.

If you test the above code in Firefox or Safari it will work perfectly, however, Chrome does not seem to properly support textPaths on circles. Chrome seems to require the use of <path> instead of <cicle>.

So my svg needs to become the following:

<svg id="mysvg" width="100%" height="100%">
  <rect x="0" y="0" width="100%" height="100%" fill="white" />
  <path id="svg_circle" d="m 0,0 a 360,360 0 1 1 720,0 360,360 0 1 1 -720,0" fill="none" />
  <text id="svg_text" fill="black">
    <textPath xlink:href="#svg_circle">my text</textPath>
  </text>
</svg>

The issue is that I cannot find any answer about how to make that <path> centre in the same way that the original <circle> does. How can I make the path draw from the centre of the SVG instead of the top left corner?

2

Answers


  1. You move the origin of an SVG by specifying a viewbox. For purposes of this demo I’ll make the viewbox 400 x 400, and I’ll set the inital x and y coordinates to -200, -200. This creates a square SVG with the origin in the centre.

    But you need to let go of the idea that your SVG should be stretching to 100% width and 100% height. You were able do this with a <circle> because you can set its centre using a percentage, but you cannot use percentages to define a <path>.

    You say that you don’t want the circle to scale, so just set the SVG to a fixed width and height. If you need a background which is larger than the SVG, just centre the SVG inside a wrapper HTML element and set the background on the wrapper instead. In this case I’ve just used the body as the wrapper, and set the background on that.

    html, body {
      height: 100%;
    }
    body {
      margin: 0;
      background: pink;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    #mysvg {
      position: fixed;
      width: 400px;
      height: 400px;
      border: 2px solid rgb(255 255 255 / 0.5);
    }
    <svg id="mysvg" viewbox="-200 -200 400 400">
      <path d="M 180 0 A 180 180 0 0 1 0 180 A 180 180 0 0 1 -180 0 A 180 180 0 0 1 0 -180 A 180 180 0 0 1 180 0 Z" id="svg_circle" fill="none"></path>
      <text id="svg_text" fill="#d70000">
        <textPath xlink:href="#svg_circle">
          Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas tempor nunc mauris, sit amet placerat tortor lobortis dapibus. Nam lectus eros, maximus ac magna vel.
        </textPath>
      </text>
    </svg>

    After running this snippet, click the full page link to see the full effect.

    Login or Signup to reply.
  2. You may wrap your text on the circle path in a <symbol> (using its own viewBox).
    This way the circle is drawn relative to its custom coordinate space.
    The <use> element can then be placed using an x offset of 50% and a fixed width to avoid scaling.

    svg{
      border: 2px solid red;
    }
    <svg id="mysvg" style="width:100%; height:100vh; background:#ccc">
      <symbol id="textCircle" viewBox="0 0 720 720" overflow="visible">
        <path id="svg_circle" d="M 0 360 
                               a 360 360 0 1 0 720 0 
                               a 360 360 0 1 0 -720 0" fill="none" stroke="red" />
        <text id="svg_text" fill="black" text-anchor="middle" font-size="40">
          <textPath href="#svg_circle" startOffset="25%">my text </textPath>
        </text>
      </symbol>
    
      <use href="#textCircle" x="50%" width="300" style="transform:translate(-150px, 0)" />
    </svg>

    BTW. by changing the sweep flag (5. parameter in the a arc command) you can also emulate the side property (currently only supported by Firefox) to change alignment of your text path (or inside outside)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search