Embed SVG in SVG?

XmlSvgEmbedding

Xml Problem Overview


I have an SVG document, and I would like to include an external svg image within it, i.e. something like:

<object data="logo.svgz" width="100" height="100" x="200" y="400"/>

("object" is just an example - the outer document will be SVG rather than xhtml).

Any ideas? Is this even possible? Or is the best thing for me to simply slap the logo.svg xml into my outer SVG document?

Xml Solutions


Solution 1 - Xml

Use the image element and reference your SVG file. For fun, save the following as recursion.svg:

<svg width="100%" height="100%" viewBox="-100 -100 200 200" version="1.1"
     xmlns="http://www.w3.org/2000/svg">
  <circle cx="-50" cy="-50" r="30" style="fill:red" />
  <image x="10" y="20" width="80" height="80" href="recursion.svg" />
</svg>

Solution 2 - Xml

Or you can actually embed child svg in parent svg like this:

<svg>
    <g>
        <svg>
            ...
        </svg>
    </g>
</svg>

demo:
http://hitokun-s.github.io/old/demo/path-between-two-svg.html

Solution 3 - Xml

It is worth mentioning that when you embed SVGs into another SVG with:

<image x="10" y="20" width="80" height="80" xlink:href="image.svg" />

then the embedded SVG takes a rectangular shape with given dimensions.

That is to say, if your embedded SVG is a circle or some shape other than a square, then it becomes a square with transparency. Therefore, mouse events get trapped into that embeded square and do not reach the parent SVG. Watch out for that.

A better approach is using a pattern. To fill a shape, either a circle, a square or even a path.

<defs>
 <pattern id="pat" x="0" y="0" width="500" height="500" patternUnits="userSpaceOnUse">
   <image x="0" y="0" width="500" height="500" xlink:href="images/mysvg.svg"></image>
 </pattern>
</defs>

Then use the pattern like this:

<circle cx="0" cy="0" r="250" fill="url(#pat)"></circle>

Now your mouse events do not get stuck into transparent image squares!

Solution 4 - Xml

I found that using the <image> tag gave a low-quality render of the embedded file. However the following technique worked (to embed an SVG file inside an SVG file - not necessarily for rendering on an HTML page):

  • Edit the SVG file in a text editor.

  • Find the end of the metadata:

     </metadata>
       <g
        id="layer1"
        inkscape:groupmode="layer"
        inkscape:label="Layer 1">
    
  • Insert this line after that group tag:

     <use xlink:href="OTHERFILE.svg#layer1" y="0" x="0" />
    
  • In this case we are including OTHERFILE.svg into the file, and all of layer1 (the first and default layer).

  • Save this and then open the file in Inkscape.

This technique is useful for having a standard background or logo on every page. By putting it first in the file it will be rendered first (and thus at the bottom). You could also lock it by adding this attribute:

sodipodi:insensitive="true" 

In other words:

<use xlink:href="OTHERFILE.svg#layer1" sodipodi:insensitive="true" y="0" x="0" />

Solution 5 - Xml

Note xlink:href has been deprecated, just use href instead, e.g.

<svg viewBox="0 0 512 512">
  <image width="512" height="512" href="external.svg"/>
</svg>

viewBox, width and height values (in this answer) are simply for illustration purpose, adjust the layout accordingly (read more).

Since <image> shares similar spec as <img>, meaning it doesn't support SVG styling, as mentioned in Christiaan's answer. For example, if I have the following css line that set the svg shape color to be the same as the font color,

svg {
  fill: currentColor;
}

The above style wouldn't apply if <image> is used. For that, you need to use <use>, as shown in Nick's answer.

Note id="layer1" and href="OTHERFILE.svg#layer1" values in his answer are mandatory.

Meaning you have to add the id attribute to the external svg file, so you need to host the (modified) external svg file by yourself (your website) or somewhere else. The resulting external svg file looks like this (notice where I put the id):

<svg id="logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
  <path d="..."/>
</svg>

The value of id can be anything, I use "logo" in this example.

To embed that svg,

<svg viewBox="0 0 512 512">
  <use href="edited-external.svg#logo"/>
</svg>

If you use the above svg as inline in your html, you don't need xmlns attribute (at least what I know from svgo).

Solution 6 - Xml

I needed to embed a SVG in my SVG but also change its color and apply transforms.

Only Firefox supports the "transform" attribute on the nested svg elements. Changing the color of <image> is also not possible. So a combination of both was needed.

What I ended up doing was the following

<svg>
  <image x="0" y="0" xlink:href="data:image/svg+xml;base64,[base64 of nested svg]"></image>
</svg>

This works on at least Firefox, Chrome and Inkscape.

This behaves the same as the child svg in the parent svg answer with the exception that you can now apply transforms on it.

Solution 7 - Xml

How about using the SVG <use> tag to embed the extra SVG?

Solution 8 - Xml

Very Easy

<image x="120" y="720" width="1000" height="900" href="assets/img/image.svg" />

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarcinView Question on Stackoverflow
Solution 1 - XmlPhrogzView Answer on Stackoverflow
Solution 2 - XmltoshiView Answer on Stackoverflow
Solution 3 - XmloabarcaView Answer on Stackoverflow
Solution 4 - XmlNick GammonView Answer on Stackoverflow
Solution 5 - XmlSafteverView Answer on Stackoverflow
Solution 6 - XmlChristiaanView Answer on Stackoverflow
Solution 7 - XmlBigman74066View Answer on Stackoverflow
Solution 8 - XmlChamara IndrajithView Answer on Stackoverflow