Home > OS >  Centering a nested SVG responsively
Centering a nested SVG responsively

Time:08-27

I've been looking for a workarround for this problem but only found fixed solutions, while I'm looking for % transform solutions.

I have an svg inside another svg, something like this:

<svg
xmlns="http://www.w3.org/2000/svg"
xmlnsXlink="http://www.w3.org/1999/xlink"
viewBox="0 0 331.45 409.46"
{...props}
> 
   <svg
      xmlns="http://www.w3.org/2000/svg"
      xmlnsXlink="http://www.w3.org/1999/xlink"
      viewBox="0 0 177.44 210.55"
      {...props}
   > </svg>
</svg>

Is it possible to center the nested svg inside of his parent? maybe using a g tag to wrap it?

CodePudding user response:

Basically, move the upper left corner of the nested <svg> to the center, and then move it by half its width to the left and half the height to the top.

There are a lot of combinations of x, y, width, height and transform that can be set on the inner <svg> element. According to the SVG 2 spec, they all are presentation attributes, which mean you can write them either as attributes or as CSS style properties. The only restriction is that if you use transform as an attribute, you must not use units.

In practice, the implementations are still incomplete on most browsers, and a lot of variants fail. For example, the following should be possible, but does not work correctly in Chrome:

<svg>
  <svg width="120px" height="90px"
       style="transform: translate(calc(50% - 60px), calc(50% - 45px))"
       viewBox="0 0 200 150">
    <rect width="200" height="150" />
  </svg>
</svg>

But it is possible to restrict yourself to what the SVG 1.1 spec allowed:

  • write everything as attributes. x, y, width, height can have all sorts of units
  • no transform on a <svg> element; instead use a <g> wrapper.

.outer {
  width: 500px;
  height: 90vh;
  border: 1px solid darkgreen;
}
<svg >
  <g transform="translate(-60 -45)">
    <svg x="50%" y="50%" width="120px" height="90px"
         viewBox="0 0 200 150">
      <rect width="200" height="150" />
    </svg>
  </g>
</svg>

  • Related