BarbuDorel
BarbuDorel

Reputation: 213

Why the <use> element in SVG doesn't work?

I have the following simple example. It is stored in image.svg:

<svg>
  <defs>
    <g id="shape">
      <circle cx="100" cy="100" r="100" />
    </g>
  </defs>
</svg>

However, putting this code in a HTML file doesn't load anything. Why is that?

<svg>
  <use xlink:href="#shape" x="10" y="10" />
</svg>

What am I doing wrong? I can't seem to make it work.

Upvotes: 9

Views: 29500

Answers (4)

Mahozad
Mahozad

Reputation: 24522

SVG 2 (when implemented in browsers) will allow to reference another SVG file without any fragment identifier:

New in SVG 2: An href without a fragment allows an entire SVG document to be referenced without having to ensure that it has an ID on its root element.

Before (SVG 1.1):

<!-- my-vector.svg -->

<svg id="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <circle r="10" cx="12" cy="12" />
</svg>
<use href="my-vector.svg#icon"></use>

After (there will be no need to define id="..." on the svg):

<!-- my-vector.svg -->

<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
  <circle r="10" cx="12" cy="12" />
</svg>
<use href="my-vector.svg"></use>

SVG 2 seems to be in the process of development in major browsers (see this Chrome feature and specifically this Chromium issue: Issue 366545: [SVG2] Allow to reference entire files).

Upvotes: 0

Ruskin
Ruskin

Reputation: 6171

For external svg files you need the namespace ... and I have added a fill to render the circle otherwise it will be transparent:

<svg xmlns="http://www.w3.org/2000/svg" >
  <symbol id="shape" width="200" height="200" viewbox="0 0 200 200">
    <circle cx="100" cy="100" r="100" fill="currentColor" />
  </symbol>
  <text y="20">Symbol above will not render unless referenced by use element</text>
</svg>

Then when you reference it you need to use the correct namespace for xlink:

svg.defs-only {
  display:block; position: absolute; 
  height:0; width:0; margin: 0; padding: 0; 
  border: none; overflow: hidden;
}

svg {
  color: orange;
  stroke: red;
}

.purple {
  color: purple;
  stroke: black;
}
<svg class="defs-only" xmlns="http://www.w3.org/2000/svg" >
  <symbol id="shape" width="50" height="50" viewbox="0 0 50 50">
    <circle cx="25" cy="25" r="20" fill="currentColor" stroke="inherit" />
  </symbol>
</svg>

<svg xmlns:xlink="http://www.w3.org/1999/xlink">
   <use xlink:href="#shape" x="10" y="10" />
   <use xlink:href="#shape" x="80" y="10" class="purple" />
</svg>

If you are referencing an external file, you need to put the filename before the # e.g. image.svg#shape making sure you get the path correct of course.

Note, not all browsers support fragment identifiers - notably IE and Edge - you need to use a javascript polyfill like svg4everybody for those browsers.

Workaround - use svg inline only

Upvotes: 8

lonesomeday
lonesomeday

Reputation: 237855

If you are using elements from another document, you have to specify the document!

<use xlink:href="#shape" x="10" y="10" />

This means "use the #shape element from the current document".

To import from another document, you need to put the reference to the SVG file in the xlink:href attribute:

<use xlink:href="image.svg#shape" x="10" y="10" />

Obviously you need to check the path is correct here. Note that this is not supported in any version of Internet Explorer, though polyfills are available.

Upvotes: 9

razemauze
razemauze

Reputation: 2676

You need to have the use-tag inside the SVG with the shape you want to use:

<svg>
    <defs>
        <g id="shape">
            <circle cx="100" cy="100" r="100" />
        </g>
    </defs>

    <use xlink:href="#shape" x="10" y="10" />
</svg>

Upvotes: 3

Related Questions