1

I'm trying to get the naturalWidth property from an SVG image on IE11. I can get the naturalWidth and naturalHeight on Chrome, Firefox, and Safari but on IE11 it always returns 0.

Here is a simple Codepen that shows the issues and here is the debug view so you can execute it on IE11 (or you can just run the code below), you will see that on IE11 the width is correct but naturalWidth is always 0.

document.getElementById('mbutton').onclick = function() {
  var divNatural = document.getElementById('natural-width');
  divNatural.innerHTML = 'Natural Width: ' + document.getElementById('msvg').naturalWidth;
  
  var divWidth = document.getElementById('width');
  divWidth.innerHTML = 'Width: ' + document.getElementById('msvg').width;
}
<button id="mbutton">Get Width</button>
<div id="natural-width">0</div>
<div id="width">0</div>

<img id="msvg" src="https://upload.wikimedia.org/wikipedia/commons/6/6b/Bitmap_VS_SVG.svg">

All the problems related to this point to not waiting for the image to load, which is not the case here, is this a known problem in IE11? Is there any workaround available?

2
  • You could try loading the file via ajax, parsing it and then read the root element width/height. I.e. do yourself what other browsers do for you. Commented Oct 23, 2019 at 5:56
  • I try to test the issue and able to reproduce the issue with IE. I found that if we use png image than code is working fine, issue only occurs with svg image. At present, it looks like any kind of bug in IE. As a work around you can try to refer the suggestion given by Robert longson. I will try to submit this bug to Microsoft. Thanks for your understanding. Commented Oct 23, 2019 at 10:25

1 Answer 1

0

Thank you to @Robert Longson, I ended up reading the dimension from the SVG file. This is not a perfect and fool-proof implementation but works quite well for my needs. With this I'm able to get the SVG width and height across all browsers:

// Load SVG into an image
var svgImage = new Image();
svgImage.onload = function () {
    // We need to attach the Image to the DOM temporarily so we can read its size on IE
    svgImage.style.opacity = 0;
    svgImage.style.position = 'fixed';
    document.body.appendChild(svgImage);

    // Save SVG width and height.              
    scope._svgHeight = svgImage.naturalHeight;
    scope._svgWidth = svgImage.naturalWidth;

    if (scope._svgHeight === 0 || scope._svgWidth === 0) {
        // On IE, naturalWidth and naturalHeight are 0 so try parsing the SVG string
        //  and see if it has width and height attributes.
        var parser = new DOMParser();
        var doc = parser.parseFromString(value, "image/svg+xml");

        if (doc && doc.firstChild && doc.firstChild.tagName === 'svg') {
            // Try getting the SVG dimensions from the width/height attributes
            var w = doc.firstChild.getAttribute('width');
            var h = doc.firstChild.getAttribute('height');
            var box = doc.firstChild.getAttribute('viewBox');

            // This regex checks if we have any non valid characters in the width (we need the dimensions
            //  to only have 'px' or no unit at all)
            var regex = /[^\d.px]/;
            if (w && h && !regex.test(w) && !regex.test(h)) {
                scope._svgWidth = parseFloat(w);
                scope._svgHeight = parseFloat(h);
            }
            else if(box) {
                // Try to use the viewbox
                var dim = box.split(' ');
                scope._svgWidth = parseFloat(dim[2]);
                scope._svgHeight = parseFloat(dim[3]);
            }
            else {
                // Fallback to width (won't work correctly in all cases)
                scope._svgWidth = svgImage.width || svgImage.offsetWidth;
                scope._svgHeight = svgImage.height || svgImage.offsetHeight;
            }
        }
        // If SVG could not be parsed fallback to width (won't work correctly in all cases)
        else {
            scope._svgWidth = svgImage.width || svgImage.offsetWidth;
            scope._svgHeight = svgImage.height || svgImage.offsetHeight;
        }
    }

    document.body.removeChild(svgImage);

    // At this point scope._svgHeight and scope._svgWidth have the width and height of the SVG
};
svgImage.src = 'data:image/svg+xml,' + encodeURIComponent(svgString);
1
  • Thanks for posting the solution for this issue. I suggest you to try to mark your own answer as an accepted answer for this question after 48 hrs, when it is available to mark. It can help other community members in future in similar kind of issues. Thanks for your understanding. Commented Oct 24, 2019 at 9:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.