A Graceful Fallback for SVGs in Old IE

Luke Haas
Share

There are plenty of good reasons to use SVGs instead of rasterized images. The benefits include better image quality, image flexibility, and smaller file size. But one obstacle you might still face is browser support. SVGs are supported by all modern browsers except IE8 and below.

In the following sections I’ll outline how you can handle this in a graceful way by falling back to PNGs for older browsers. This will address both inline SVGs and background images.

Produce your Fallback Images

The first step is to produce a PNG version for each of your SVGs. You could do this with your preferred image editing software, but that could be a slow process if you have a lot of SVGs. Alternatively, you can use Grunt and a Grunt module called svg2png. This is the solution I will be describing in the following steps.

If you’re not familiar with Grunt, I recommend you read through this getting started guide. Otherwise, you can make a start by preparing a Grunt project and then running the following command:

npm install grunt-svg2png --save-dev`

Configure Your Grunt File

Configure your Grunt file with the following additions:

grunt.loadNpmTasks('grunt-svg2png');

grunt.initConfig({
    svg2png: {
        all: {
            files: [
                { cwd: 'img/', src: ['**/*.svg'], dest: 'img/png/' }
            ]
        }
    }
});

Make sure to point the cwd property to the directory containing your SVGs. Once that’s done, run grunt svg2png and you should now have a folder full of PNG versions of your SVG files.

Handling Inline SVGs

If you are using SVGs as inline images, the most robust fallback is to add an inline onerror event to the image tag like this:

<img src="/img/image.svg" onerror="this.src='/img/image.png';this.onerror=null;">

This will swap out the SVG for the PNG image if the SVG fails to load. I’ve also added an extra bit at the end: this.onerror=null;. This is to stop the event from firing again, which could happen if there was an issue with the path of the PNG. This would then cause an infinite loop of event calls, which is obviously best avoided.

You may be wondering why I’m suggesting an inline event here rather than a less obtrusive approach of attaching an event in a separate JavaScript file. This is because a jQuery approach of $("img").on("error", handler); won’t work in IE8 and lower because of timing issues, and the other alternative of looping through all images and attaching an error event to them would be a drain on resources for all browsers unless you just targeted older ones.

Handling SVGs as Backgrounds

If you are using SVGs as background images in your CSS then there’s a simple way to fall back to PNGs. The support for SVG is roughly in line with support for multiple background images. This means you can use a pure CSS solution, and so the following declarations are all you need:

background: url('/img/image.png') no-repeat;
background: none,
            url('/img/image.svg') no-repeat;

Here we are setting a PNG as the background but then overriding it with an SVG for browsers that are able to support multiple backgrounds on the second line.

IE8 and lower will view the second declaration as an error, so it will ignore the entire line, using only the first background.

Conclusion

That’s all there is to it. Now I hope going forward you’ll use SVGs even in projects that still require support for older versions of IE. This means you’ll be safe in the knowledge that they can gracefully degrade to PNGs if needed.

If you have some other automated solution for dealing with SVGs in IE8 and below, I’d love to hear about it.