112

What is the proper way to get the dimensions of an svg element?

http://jsfiddle.net/langdonx/Xkv3X/

Chrome 28:

style x
client 300x100
offset 300x100

IE 10:

stylex 
client300x100 
offsetundefinedxundefined 

FireFox 23:

"style" "x"
"client" "0x0"
"offset" "undefinedxundefined"

There are width and height properties on svg1, but .width.baseVal.value is only set if I set the width and height attributes on the element.


The fiddle looks like this:

HTML

<svg id="svg1" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="red" />
    <circle cx="150" cy="50" r="40" stroke="black" stroke-width="1" fill="green" />
    <circle cx="250" cy="50" r="40" stroke="black" stroke-width="1" fill="blue" />
</svg>

JS

var svg1 = document.getElementById('svg1');

console.log(svg1);
console.log('style', svg1.style.width + 'x' + svg1.style.height);
console.log('client', svg1.clientWidth + 'x' + svg1.clientHeight);
console.log('offset', svg1.offsetWidth + 'x' + svg1.offsetHeight);

CSS

#svg1 {
    width: 300px;
    height: 100px;
}
Langdon
  • 19,875
  • 18
  • 88
  • 107

8 Answers8

134

Use the getBBox function:

The SVGGraphicsElement.getBBox() method allows us to determine the coordinates of the smallest rectangle in which the object fits. [...]

http://jsfiddle.net/Xkv3X/1/

var bBox = svg1.getBBox();
console.log('XxY', bBox.x + 'x' + bBox.y);
console.log('size', bBox.width + 'x' + bBox.height);
Behrang
  • 46,888
  • 25
  • 118
  • 160
Pavel Gruba
  • 1,999
  • 1
  • 12
  • 8
  • 15
    Is there no way to treat it like an HTML element and get the actual size the `svg` element is occupying despite what has been drawn? http://jsfiddle.net/Xkv3X/4/ – Langdon Aug 09 '13 at 13:51
  • 4
    Btw, I'm trying to determine the size of the canvas that I can draw on before rendering shapes. – Langdon Aug 09 '13 at 13:53
  • 1
    I think it might be better to check available size of container (the div which contains your svg) then you can set appropriate size to you svg – Pavel Gruba Aug 09 '13 at 13:58
  • That seems to be the only cross-browser way to do it... `getBoundingClientRect` gives me 400x400 in Chrome28, but FireFox23 reports 281x81. – Langdon Aug 09 '13 at 14:00
  • 1
    @Langdon that's just been fixed in Firefox. Firefox 33 will report something similar to Chrome. – Robert Longson Jul 09 '14 at 09:20
  • 2
    Today I reported a problem with getBoundingClientRect for FireFox 38 when symbol/use are used. In this case getBoundingClientRect extends the element to the border of viewBox. Also there is a known issue about stroke-width. So getBoundingClientRect is not cross browser solution for now. – Dzenly Oct 12 '15 at 18:36
  • https://caniuse.com/#feat=getboundingclientrect - all looks okay now, FF12+, Chrome 4+. I suspect those FF bugs get fixed in the same major version numbers as minor updates. – marksyzm Oct 19 '18 at 13:55
  • This doesn't take into account scale. My SVG element with CSS `transform: scale(5, 5)`, and which renders as 17000x3000 returns getBBox() of only 600x100. – Cerin Feb 08 '21 at 15:43
71

FireFox have problemes for getBBox(), i need to do this in vanillaJS.

I've a better Way and is the same result as real svg.getBBox() function !

With this good post : Get the real size of a SVG/G element

var el   = document.getElementById("yourElement"); // or other selector like querySelector()
var rect = el.getBoundingClientRect(); // get the bounding rectangle

console.log( rect.width );
console.log( rect.height);
obysky
  • 761
  • 5
  • 8
9

I'm using Firefox, and my working solution is very close to obysky. The only difference is that the method you call in an svg element will return multiple rects and you need to select the first one.

var chart = document.getElementsByClassName("chart")[0];
var width = chart.getClientRects()[0].width;
var height = chart.getClientRects()[0].height;
Cichelero
  • 321
  • 1
  • 3
  • 7
8

SVG has properties width and height. They return an object SVGAnimatedLength with two properties: animVal and baseVal. This interface is used for animation, where baseVal is the value before animation. From what I can see, this method returns consistent values in both Chrome and Firefox, so I think it can also be used to get calculated size of SVG.

afkatja
  • 301
  • 4
  • 13
  • where svg is your element... let svgWidth = svg.width.baseVal.value ; let svgHeight = svg.height.baseVal.value ; – Bob Aug 09 '19 at 11:02
  • Unfortunately this doesn't work on Firefox at the moment - it'll give you an initial value but if you change the svg dimensions and try it again it gives you the original value. – Bob Aug 09 '19 at 19:32
4

This is the consistent cross-browser way I found:

var heightComponents = ['height', 'paddingTop', 'paddingBottom', 'borderTopWidth', 'borderBottomWidth'],
    widthComponents = ['width', 'paddingLeft', 'paddingRight', 'borderLeftWidth', 'borderRightWidth'];

var svgCalculateSize = function (el) {

    var gCS = window.getComputedStyle(el), // using gCS because IE8- has no support for svg anyway
        bounds = {
            width: 0,
            height: 0
        };

    heightComponents.forEach(function (css) { 
        bounds.height += parseFloat(gCS[css]);
    });
    widthComponents.forEach(function (css) {
        bounds.width += parseFloat(gCS[css]);
    });
    return bounds;
};
Sergio
  • 28,539
  • 11
  • 85
  • 132
3

From Firefox 33 onwards you can call getBoundingClientRect() and it will work normally, i.e. in the question above it will return 300 x 100.

Firefox 33 will be released on 14th October 2014 but the fix is already in Firefox nightlies if you want to try it out.

Robert Longson
  • 118,664
  • 26
  • 252
  • 242
2

Use .getAttribute()!

var height = document.getElementById('rect').getAttribute("height");
var width = document.getElementById('rect').getAttribute("width");
var x = document.getElementById('rect').getAttribute("x");
alert("height: " + height + ", width: " + width + ", x: " + x);
<svg width="500" height="500">
  <rect width="300" height="100" x="50" y="50" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" id="rect"/>
</svg>
Piuksu
  • 117
  • 1
  • 8
0

A save method to determine the width and height unit of any element (no padding, no margin) is the following:

let div   = document.querySelector("div");
let style = getComputedStyle(div);

let width  = parseFloat(style.width.replace("px", ""));
let height = parseFloat(style.height.replace("px", ""));
Martin Wantke
  • 4,287
  • 33
  • 21