This isn't the most robust solution, but this hack worked for our purposes. Extract viewBox data and use these dimensions for the width/height attributes.
This only works if the first viewBox encountered has a size that accurately can represent the size of the SVG document, which will not be true for all cases.
// @svgDoc is some SVG document. let svgSize = getSvgViewBox(svgDoc); // No SVG size? if (!svgSize.width || !svgSize.height) { console.log('Image is missing width or height'); // Have size, resolve with new SVG image data. } else { // Rewrite SVG doc let unit = 'px'; $('svg', svgDoc).attr('width', svgSize.width + unit); $('svg', svgDoc).attr('height', svgSize.height + unit); // Get data URL for new SVG. let svgDataUrl = svgDocToDataURL(svgDoc); } function getSvgViewBox(svgDoc) { if (svgDoc) { // Get viewBox from SVG doc. let viewBox = $(svgDoc).find('svg').prop('viewBox').baseVal; // Have viewBox? if (viewBox) { return { width: viewBox.width, height: viewBox.height } } } // If here, no viewBox found so return null case. return { width: null, height: null } } function svgDocToDataURL(svgDoc, base64) { // Set SVG prefix. const svgPrefix = "data:image/svg+xml;"; // Serialize SVG doc. var svgData = new XMLSerializer().serializeToString(svgDoc); // Base64? Return Base64-encoding for data URL. if (base64) { var base64Data = btoa(svgData); return svgPrefix + "base64," + base64Data; // Nope, not Base64. Return URL-encoding for data URL. } else { var urlData = encodeURIComponent(svgData); return svgPrefix + "charset=utf8," + urlData; } }
<svg>element. If it does are those attribute values percentages?drawImage()didn't even throw an error. Adding width/height in the <svg> did fix it!