Skip to content

Instantly share code, notes, and snippets.

@schmidt1024
Created June 3, 2015 13:59
Show Gist options
  • Save schmidt1024/61beeca2cce94a70c9df to your computer and use it in GitHub Desktop.
Save schmidt1024/61beeca2cce94a70c9df to your computer and use it in GitHub Desktop.
Replace all SVG images with inline SVG using jQuery
/*
* Replace all SVG images with inline SVG
*/
jQuery('img.svg').each(function(){
var $img = jQuery(this);
var imgID = $img.attr('id');
var imgClass = $img.attr('class');
var imgURL = $img.attr('src');
jQuery.get(imgURL, function(data) {
// Get the SVG tag, ignore the rest
var $svg = jQuery(data).find('svg');
// Add replaced image's ID to the new SVG
if(typeof imgID !== 'undefined') {
$svg = $svg.attr('id', imgID);
}
// Add replaced image's classes to the new SVG
if(typeof imgClass !== 'undefined') {
$svg = $svg.attr('class', imgClass+' replaced-svg');
}
// Remove any invalid XML tags as per http://validator.w3.org
$svg = $svg.removeAttr('xmlns:a');
// Replace image with new SVG
$img.replaceWith($svg);
}, 'xml');
});
@bondo11
Copy link

bondo11 commented Oct 26, 2018

and here is my take on it, in typescript, where it is unittestable
use it like this:
new InlineSvg().execute();

and add the class "svg-inline", to the svgs you want to inline

export default class InlineSvg {
    private imageElements: HTMLImageElement[];
    private svgElements: HTMLImageElement[];
    private classToReplace: string = "svg-inline";

    constructor() {
        this.imageElements = Array.from(document.querySelectorAll<HTMLImageElement>("img")) as HTMLImageElement[];
        this.svgElements = this.imageElements.filter((x: HTMLImageElement) =>x.classList.contains(this.classToReplace));
    }

    execute(): void {
        this.svgElements.forEach((x: HTMLImageElement) => {
            this.getSvg(x, x.src);
        });
    }

    replace(source: HTMLImageElement, target: HTMLElement): void {
        // add replaced image's ID to the new SVG
        if(typeof source.id !== "undefined") {
            target.id = source.id;
        }

        // add replaced image's classes to the new SVG
        source.classList.forEach((x: string) => {
            if(x===this.classToReplace) { return; }
            target.classList.add(x);
        });

        target.classList.add("replaced-svg");

        // remove any invalid XML tags as per http://validator.w3.org
        target.removeAttribute("xmlns:a");

        // replace image with new SVG
        source.replaceWith(target);
    }

    getSvg(source: HTMLImageElement, url: string): void {
        const http: XMLHttpRequest = new XMLHttpRequest();
        http.open("GET", url, true);
        http.setRequestHeader("Content-Type", "text/xml; charset=UTF-8");
        http.onload = () => {
            if(http.readyState === http.DONE && http.status === 200) {
                const target: HTMLElement = http.responseXML.documentElement;
                this.replace(source, target);
            }
        };
        http.send(null);
    }
}

@danielgroner
Copy link

Another simple but important addition could be to also get the replaced image's alt tag.

var imgAlt = $img.attr('alt');

// add replaced image's alt tag to the new SVG
if(typeof imgAlt !== 'undefined') {
        $svg = $svg.attr('alt', imgAlt);
}

@usame-algan
Copy link

usame-algan commented Nov 12, 2019

@z1haze @engray I've adjusted the plain Javascript version to work with fetch.

document.querySelectorAll('img.svg').forEach((el) => {
      const imgID = el.getAttribute('id');
      const imgClass = el.getAttribute('class');
      const imgURL = el.getAttribute('src');

      fetch(imgURL)
          .then(data => data.text())
          .then(response => {
                const parser = new DOMParser();
                const xmlDoc = parser.parseFromString(response, 'text/html');
                let svg = xmlDoc.querySelector('svg');

                if (typeof imgID !== 'undefined') {
                    svg.setAttribute('id', imgID);
                }

                if(typeof imgClass !== 'undefined') {
                    svg.setAttribute('class', imgClass + ' replaced-svg');
                }

                svg.removeAttribute('xmlns:a');

                el.parentNode.replaceChild(svg, el);
          })
});

@amohamdy
Copy link

amohamdy commented Jan 2, 2020

this code doesn't work on internet explorer any solution for this issue??

@subfighter3
Copy link

Great code btw, really useful.
If you need it in ES6:

   $('img.svg').each((i, e) => {

    const $img = $(e);

    const imgID = $img.attr('id');

    const imgClass = $img.attr('class');

    const imgURL = $img.attr('src');

    $.get(imgURL, (data) => {
        // Get the SVG tag, ignore the rest
        let $svg = $(data).find('svg');

        // Add replaced image's ID to the new SVG
        if (typeof imgID !== 'undefined') {
            $svg = $svg.attr('id', imgID);
        }
        // Add replaced image's classes to the new SVG
        if (typeof imgClass !== 'undefined') {
            $svg = $svg.attr('class', `${imgClass}replaced-svg`);
        }

        // Remove any invalid XML tags as per http://validator.w3.org
        $svg = $svg.removeAttr('xmlns:a');

        // Check if the viewport is set, if the viewport is not set the SVG wont't scale.
        if (!$svg.attr('viewBox') && $svg.attr('height') && $svg.attr('width')) {
            $svg.attr(`viewBox 0 0  ${$svg.attr('height')} ${$svg.attr('width')}`);
        }

        // Replace image with new SVG
        $img.replaceWith($svg);
    }, 'xml');
});

Thank you @VinceVachon, I found a small error here:
$svg = $svg.attr("class", ${imgClass}replaced-svg);

I added a space between the original classes and "replaced-img" new class:
$svg = $svg.attr("class", ${imgClass} replaced-svg);

While the plain JS version provided by @usame-algan gives me an error: "fetch(...) is undefined" and is not working for me...

Anyway thank everybody for contributing on this useful tool!

@panatapattu
Copy link

This is a great solution. Is there any way to use this with owl carousel? When new carousel items loading, those are not rendering to SVGs.

@Warface
Copy link

Warface commented Jan 19, 2023

this code doesn't work on internet explorer any solution for this issue??

Yeah don't use Internet Explorer ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment