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.

Discussion (3)

Collapse
stereobooster profile image
stereobooster

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

Collapse
nlxdodge profile image
NLxDoDge

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

Collapse
chandra profile image
Chandra Prakash Tiwari

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