<href> in SVG
While creating an animated SVG logo for Indietech.rocks we ran into a strange problem where the SVG would display in some browsers and not in others. The issue is the different ways browsers handle XML — yes SVG is XML! So here is the problem and its solution.
<symbol>
and <use>
are very useful when creating SVGs. The <symbol>
-tag defines a piece of SVG markup that can be reused repeatedly inside the SVG document. Whenever we want to use — that is, actually display — the defined symbol we simply link to it from a <use>
-tag, just like we would use an <a>
-tag to create hyperlinks.
As an example, let’s create an SVG with a symbol that defines a simple circle. Then we can use this circle elsewhere in the SVG by refering to the id
attribute of the symbol using the href
attribute of the <use>
-tag.
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<symbol id="circ"><circle cx="100" cy="100" r="100"/></symbol>
<use href="#circ"/>
</svg>
Now we can either use this SVG as an external source in <img>
or embed it directly in the HTML page, as in the below figure.
Now, if you are using Safari you might not see any circles in the above image, but they both show up in Firefox, Chrome and Opera.
The problem is that the href
attribute was defined in the 2.0 version of the SVG specification but not in the 1.1 version. I think Safari uses the older specification and so does not recognise the href
attribute in <use>
.
To fix this we have to use the xlink:href
attribute instead.
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" version="1.1">
<symbol id="circ"><circle cx="100" cy="100" r="100"/></symbol>
<use xlink:href="#circ"/>
</svg>
Now the embedded SVG is displayed in all browsers but the external one linked from an img
does not display in Firefox, Chrome or Opera; so we fixed the issue for Safari but seemed to have messed it up for other browsers!
If you open the embedded image in Firefox it shows the error “XML Parsing Error: prefix not bound to a namespace
”. It seems that browsers other than Safari do not understand the xlink
-prefix to the href
attribute. Blame this on the really excessive namespacing in XML.
The solution is to add an XML namespace for the xlink
prefix. We can do this by adding xmlns:xlink="http://www.w3.org/1999/xlink"
to the <svg>
element.
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" version="1.1" xmlns:xlink="http://www.w3.org/1999/xlink">
<symbol id="circ"><circle cx="100" cy="100" r="100"/></symbol>
<use xlink:href="#circ"/>
</svg>
Now both images should display in all browsers… phew!