24

I create a svg element in javascript and I need to set an attribute which is case sensitive: viewBox.

The element is created like this: var svgElem = document.createElement('svg');

Problem is when it set that attribute via svgElem.setAttribute("viewBox", "0,0,100,100") and append to the DOM, the resulting element shows like this: <svg viewbox="0,0,100,100"></svg>

This doesn't work because the viewBox is case sensitive, it will not take any effect if the letter B is lowercase.

IE allows an IFlag parameter just for cases like these, however my target audience is restricted to FireFox and Chrome users, which do not have IFlag for setAttribute as far as I could find.

Is there a way of making this work without using innerHTML and no-library javascript?

EDIT: I have also tried using dot notation with no success svg.viewBox = "0,0,100,100"

Shadow
  • 4,168
  • 5
  • 41
  • 72

4 Answers4

42

You need to create an actual svg element. When you do:

var svg = document.createElement('svg');

what you are actually getting is an HTML element named svg, not an SVG element. The key here is that SVG is not actually an HTML element at all, it is a foreign document root. To create an SVG element properly, you need to do

var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');

Specifically, this creates an XML element, rather than an HTML element. In the basic browser case,

document.createElement('div')

is the same as

document.createElementNS('http://www.w3.org/1999/xhtml', 'div');

This makes a big difference, because in HTML, attribute names are not case-sensitive, whereas in XML, they are. Also, if you were to append that SVG to the DOM, it would behave like a div since it is an unknown HTML element, rather than a real SVG element. An HTML parser is smart enough to create a foreign root node instead of an unknown HTML element, but your code is programmatic, so it can't do it automatically.

loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • `div.setAttributeNS("http://www.w3.org/2000/svg", "name", "value")` This would retain the case of the name. – xplorer1 May 11 '20 at 12:25
  • @xplorer1 Sure but that means the element itself has the HTML namespace, which isn't something anyone's likely to want. – loganfsmyth Feb 19 '23 at 18:16
4

It works fine for me in Chrome and Firefox.

var  svgns = "http://www.w3.org/2000/svg";

var  svg = document.createElementNS(svgns, "svg");
svg.setAttribute("width", "400");
svg.setAttribute("height", "400");

var  circle = document.createElementNS(svgns, "circle");
circle.setAttribute("cx", "300");
circle.setAttribute("cy", "300");
circle.setAttribute("r", "100");
svg.appendChild(circle);

document.getElementById("container").appendChild(svg);

// Now change the viewBox
svg.setAttribute("viewBox", "200 200 200 200");
<div id="container">
</div>

(Note: updated to create the SVG from scratch as per OPs request)

Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • The svg you are using was not created via javascript, it was already written in the html. I clearly stated in the beginning of my question that `"I create a svg element in javascript ..."` – Shadow Feb 26 '15 at 05:04
  • It shouldn't matter how it was created. – Paul LeBeau Feb 26 '15 at 05:06
  • 1
    No it shouldn't, but it sadly does and I don't understand the reason behind it. – Shadow Feb 26 '15 at 05:07
  • I was using the common `createElement` method instead of the correct one. Unfortunately I have already accepted someone else's answer before your edit, I am sorry that I can't accept more than one answer, however I still can vote your answer as being useful. – Shadow Feb 26 '15 at 05:22
  • this works for me (in Firefox) when I run the example on stackoverflow, but when I run the exact same code in the console for my page, it doesn't work! I'm stuck with lowercase "viewbox". Baffling! My page even has the same doctype as the stackoverflow example frame! – micahscopes Feb 23 '17 at 01:44
3

For HTMLElement, just change setAttribute("attrName", "value") to setAttributeNS(null,"attrName", "value"), resolved my problem.

see this post :

'setAttributeNS()' doesn't convert the name to lower case.

Amir Azizkhani
  • 1,662
  • 17
  • 30
  • The question specifically asks about SVG, and as the accepted answer states, it is an XML rather than an HTML element. – Asinus Rex Nov 28 '18 at 16:03
  • 1
    @AsinusRex But the question title does not. And I am happy about this answer as it exactly solves my problem which is derived from the exact same question (title). – Jack Fuchs Feb 18 '21 at 11:12
0

You should create the value using createAttribute, see Setting attribute value of an element in camelCase using a directive

var div1 = document.createElementNS("http://blabla/svg", "view");
var attr1 = document.createAttribute("viewBox");
attr1.value = "200 200 200 200";
div1.setAttributeNode(attr1);
Community
  • 1
  • 1
Milagros
  • 1
  • 1