I was trying to manipulate SVG in plain JS and found that it won't behave as intended if I don't use methods like createElementNS
and setAttributeNS
.
<svg id="mydsvg" width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
The above markup works perfectly. But if you try to add another circle via the following code, you won't see it.
var circle = createElement('circle');
circle.setAttribute('cx', 50);
....
document.getElementById('mysvg').appendChild(circle);
But if you use createElementNS
and setAttributeNS
, it will work as expected.
To be worst, both createElement
and createElementNS
create identical DOM text.
It doesn't work because the specifications say that SVG elements must exist in the SVG namespace and createElement creates elements in the html namepace. How would a parser know otherwise whether you wanted to create an html <a>
element which works with a src attribute or a SVG <a>
element for which an `xlink:href attribute is required.
In html where namespaces are not serialized things look the same. In XML where namespaces are serialized they don't.
SVG in html looks like this...
<svg id="mydsvg" width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
SVG as a standalone document would look like this
<svg xmlns="https://www.w3.org/2000/svg" id="mydsvg" width="100" height="100">
<circle cx="50" cy="50" r="40" stroke="green" stroke-width="4" fill="yellow" />
</svg>
The circle inherits the namespace of its parent.