DEV Community

Benjamin Black
Benjamin Black

Posted on • Updated on

Using a string of SVG text as an image source

My posts are usually notes and reference materials for myself, which I publish here with the hope that others might find them useful.

TL;DR:

let svg = `<svg xmlns="http://www.w3.org/2000/svg" ...`;
let blob = new Blob([svg], {type: 'image/svg+xml'});
let url = URL.createObjectURL(blob);
let image = document.createElement('img');
image.src = url;
image.addEventListener('load', () => URL.revokeObjectURL(url), {once: true});
Enter fullscreen mode Exit fullscreen mode

It is sometimes useful to compose an SVG programmatically as a string. Using that string as the src of an image is fairly straightforward (with one "gotcha".)

Step one: you need a string of SVG text.

let svg = `<svg ...`;
Enter fullscreen mode Exit fullscreen mode

Step two: convert the string to a blob.

let blob = new Blob([svg], {type: 'image/svg+xml'});
Enter fullscreen mode Exit fullscreen mode

Step three: create a URL to the blob.

let url = URL.createObjectURL(blob);
Enter fullscreen mode Exit fullscreen mode

Step four: create an image referencing the URL.

let image = document.createElement('img');
image.src = url;
Enter fullscreen mode Exit fullscreen mode

Step five: revoke the URL once the image loads for cleanup.

image.addEventListener('load', () => URL.revokeObjectURL(url), {once: true});
Enter fullscreen mode Exit fullscreen mode

However, the following does not work:

let svg = `
<svg width="50" height="50">
    <circle cx="25" cy="25" r="20"/>
</svg>`;
Enter fullscreen mode Exit fullscreen mode

This results in a broken image:

broken image

The xmlns attribute must be included on the <svg> element:

let svg = `
<svg width="50" height="50" xmlns="http://www.w3.org/2000/svg">
   <circle cx="25" cy="25" r="20"/>
</svg>`;
Enter fullscreen mode Exit fullscreen mode

And now it works:

working image

Chrome is not tolerant of a missing xmlns attribute in this case, which is, I guess, consistent: only inline <svg>s, embedded inside HTML markup, are allowed to omit the xmlns attribute. External SVGs, used as the src of an <img>, must include it, apparently even if the SVG is "inline" in the sense that it created by the document itself as a blob, and even if the MIME type is image/svg+xml.

Top comments (4)

Collapse
 
stereobooster profile image
stereobooster

Second option would be data:image/svg+xml, and encodeURIComponent. See codepen.io/tigt/post/optimizing-sv...

Collapse
 
chandra profile image
Chandra Prakash Tiwari

Blob is not defined in Node.js file?? Any Suggestions?

Collapse
 
hayesmaker profile image
hayesmaker

This is code designed to run in the browser, not in Node.

Collapse
 
nlxdodge profile image
NLxDoDge

This saved me some hours of search for a solution, Thanks :)