Better Positioning and Transforming With Nested SVG
The creation of SVG graphics is pretty straightforward. If you know HTML, you’ll be able to handle the SVG syntax quickly. However, there are a couple of small, but relevant differences between HTML and SVG regarding the positioning of SVG shapes. These are placed entirely within an SVG drawing space.
How Shapes Are Placed in SVG Graphics
When it comes to the positioning of SVG elements like “<rect>” or “<circle>”, there’s already a big difference to HTML regarding the syntax. While HTML elements are placed via CSS attributes “left” and “top”, SVG elements can only be placed via “x” and “y” attributes (“cx” and “cy” attributes for circles).
While, with CSS, colors and contours can be designed via CSS, a positioning via CSS isn’t even possible in SVG format.
The second difference is that SVG shapes are generally placed within an “<svg>” element. Although the “<g>” element gives us an opportunity to group elements, it is not possible to assign a position to the “<g>” element itself.
This poses a problem when it comes to sophisticated graphics. Because, if you want to change the position of a figure that possibly consists of dozens of individual elements, the “x” and “y” attribute, as well as the other position defining attributes, like “cx”, “cy”, and “d” (for the “<path>” element), have to be altered.
This problem is pretty easy to fix for static graphics, by opening the graphic in a drawing program, like Illustrator. There, you get to adjust everything and save it as an SVG file.
Nesting SVGs While Still Placing Them Relatively
However, there is a way to place SVG forms relatively within an SVG graphic. The SVG format allows for the nesting of SVG graphics.
It is possible for an “<svg>” elements, to be placed within another “<svg>” element. Though, within a nesting, the absolute placement is limited to the respective parent “<svg>” element.
<svg width="750" height="500" style="background: gray"> <svg x="200" y="200"> <circle cx="50" cy="50" r="50" style="fill: red" /> </svg> <circle cx="50" cy="50" r="50" style="fill: yellow" /> </svg>
In the example, a circle is being drawn on the in and outside of a nested SVG graphic. The circles are placed so that they are at the top left corner. As the nested “<svg>” element is 200 pixels away from the top left border, the red circle is also placed 200 pixels away from both borders.
Changing the “x” and “y” attributes of the second “<svg>” element also changes the placement of all included shapes.
In contrast to the “<g>” element, the nested “<svg>” elements allow you to change the position of multiple shapes at once.
The CSS attribute “transform” not only scales and rotates HTML elements, but SVG shapes as well. However, the SVG interpretation of “transform” is different from the HTML one.
This becomes very noticeable with the “rotate()” function. With HTML, “rotate()” makes the elements rotate around their own center.
However, in SVG format, elements are always turned around the top left corner of the SVG drawing area. Of course, this makes it difficult to realize rotations. If you want to put a text upright, rotating it by 90 degrees won’t do the trick. The “x” and “y” attributes need to be adjusted as well.
An element that is placed 200 pixels from the left and the top, and rotated by 90 degrees counterclockwise may disappear from the drawing space.
However, you can use nested SVG elements to help you with this as well. While you won’t be able to make elements rotate around their own center, the adjustment of the position becomes rather easy if you place the elements you want to rotate at the top left of the nested “<svg>” element.
<svg width="750" height="500" style="background: gray"> <svg x="100" y="100"> <rect x="0" y="0" width="142" height="142" style="fill: yellow" /> <rect x="50" y="-50" width="100" height="100" style="fill: black; transform: rotate(45deg)" /> </svg> </svg>
In this example, two rectangles are placed within a nested “<svg>” element. While the first one works fine without a “transform” attribute, that attribute and the “rotate()” function are what rotates the second one by 45 degrees.
To make the second rectangle start with the top left position of the first one, the “x” and “y” attributes need to be altered. Without this adjustment, the second rectangle would be rotated to the left, around the corner of the nested “<svg>” element and half of it would point out of the drawing space.
This becomes even more challenging because the placement depends on the rotation. The coordinate system of the rotated shape is rotated as well. Thus, the value of “x” is not based on the horizontal anymore, but rather on an axis rotated by 45 degrees.
Another Advantage of Nested SVGs
There’s another benefit – or, at least, something to keep in mind. An “<svg>” element allows you to assign color and contour via CSS. If there is no color or contour assigned to the shapes within the drawing area, they all assume the appearance of the SVG parent element.
<svg width="750" height="500" style="background: gray"> <svg x="100" y="100" style="fill: yellow; stroke: red"> <rect x="0" y="0" width="142" height="142" /> <rect x="100" y="-50" width="100" height="100" style="transform: rotate(45deg)" /> </svg> </svg>
This way, giving a homogenous look to all elements of an SVG drawing space is possible, and uncomplicated.