I want to achieve a layout of several SVG's as illustrated below.
The gray box is the top-level SVG containing the other elements. The width and height is known.
The orange boxes contain the red boxes and need to retain the same distance from each other. Similar to how justify-content: space-around aligns items.
The red boxes also retain their distance in the same way (but vertically).
I've been trying to adjust the positioning with transform-origin but it does not seem to work. Instead the offset is always calculated from the top-left of each element, which pushes the elements out of view. This is a very basic snippet, but it's all I have sadly.
<svg width="400" height="400" style="background:#ccc;">
<g transform="translate(10, 10)">
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
</g>
<g transform="translate(200, 10)">
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
</g>
<g transform="translate(360, 10)">
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
<svg width="50" height="50">
<rect width="50" height="50" fill="red" />
</svg>
</g>
</svg>
Is there a way to align these containers this way without knowing the size of the red boxes? Every solution I end up with uses some calculation where I would need to subtract half the width and height of the red boxes.
CodePudding user response:
As pointed out in a comment @enxaneta :
Instead of using all those nested svg elements you can put a rect in the defs. the rect would be centered around the point 0,0
In SVG, element positions are relative to the top left corner of the canvas.
If you specify the same x=40 coordinates for several rectangles, then they will be vertically aligned.
In order not to write for each rectangle the values of its coordinates, as well as the values of width and height, you need to place one instance in the <defs> section and then clone it using the <use> tag.
In this case, you need to specify the coordinates x,y for each copy:
<use xlink:href="#rect" x="40" y="62.5" />
To get three columns you need to wrap one column in a <g> group tag and clone it with <use>
<use xlink:href="#column" x="150" y="0" />
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="450" height="400" viewBox="0 0 450 400" style="background:#ccc;">
<defs>
<rect id="rect" width="50" height="50" fill="red" x="0" y="0" />
</defs>
<g id="column" >
<rect x="30" y="0" width="70" height="400" fill="#C89F33" />
<use xlink:href="#rect" x="40" y="62.5" />
<use xlink:href="#rect" x="40" y="175" />
<use xlink:href="#rect" x="40" y="287.5" />
</g>
<use xlink:href="#column" x="150" y="0" />
<use xlink:href="#column" x="300" y="0" />
</svg>

