We where tasked/needed to serialize SVG files on a project we are working on, and while the first implementation worked well on most (normal) browsers, it did not take too long time before we got some complains that our images where not being displayed properly.
After some debugging we found out that all these cases where related to users using IE. And after dusting of my Windows laptop and started testing we could reproduce the issue ❤️ (as developer I get a relief when I can reproduce an bug)
After a quick search on Google for IE svg adding double xmlns
following two links helped understanding the issue and led to a fix:
- Unwanted namespaces on SVG markup when using XMLSerializer in JavaScript with IE
- Highcharts adds duplicate xmlns attribute to SVG element in IE
First implementation (Does NOT work on IE)
We do use Figma to design and create our SVG's, when exporting, the SVG contains the xmlns
-tag by default.
Here is an SVG example showing a red circle where the xmlns
-tag is already set:
<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red" />
</svg>
The serialize function we used is straight forward using XMLSerializer
:
export const svgSerialize = (el: SVGSVGElement) => new XMLSerializer().serializeToString(el);
This will result in following result:
<svg height="100" width="100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red"/></svg>
And as said this worked perfectly on all other browsers expect Internet Explorer. Here is the result of same image on IE:
<svg xmlns="http://www.w3.org/2000/svg" height="100" width="100" xmlns="http://www.w3.org/2000/svg"><circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red"/></svg>
Yes you spotted right, yet another xmlns="http://www.w3.org/2000/svg"
-tag has been added to the SVG :(
Browsers are strict on XML parsing and therefor the above image will not be displayed!
After some trial and errors here is how we fixed the issue.
The solution
First we removed xmlns
tag from our SVG:
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red" />
</svg>
And our new svgImageToString function looks like this:
export const svgImageToString = (el: SVGSVGElement) => {
// Serialize the SVG object, this will add an xmlns on IE
const serialized = new XMLSerializer().serializeToString(el);
// We then do convert back the SVG serialized string to new SVG
const parser = new DOMParser();
const newSvg = parser.parseFromString(serialized, "image/svg+xml");
const newSvgEl = newSvg.firstChild as SVGSVGElement;
// We check if the new SVG has xmlns if not we added to it
if(!newSvgEl.hasAttribute('xmlns')){
newSvgEl.setAttribute('xmlns', 'http://www.w3.org/2000/svg')
}
// We serialize the new element again and return the result
return new XMLSerializer().serializeToString(newSvgEl)
}
You are probably thinking why converting the SVG serialized string back to SVG object using DOMParser, due to our complex SVG's we where not able to detect and remove the double xmlns
-tag in another way (yes we tried with regex).
Hope this will help others that will face this issue 😊
Comment if you have other alternatives to the solution!
Cheers :)
Top comments (0)