Test for Support of SVG as img

Avatar of Chris Coyier
Chris Coyier on (Updated on )

Browser support for SVG isn’t quite as simple as yes or no. In addition to some quirks on how that support plays out, it depends on how that SVG is being used. One common way is right within an image tag, like <img src="image.svg" alt="description">.

How can you detect if a browser supports SVG use in that way?

It’s one thing to just know which browsers do. The only real danger zones are IE 8- and Android 2.3. You could do user agent detection, and while I wouldn’t want to get too judgey about that, it’s generally a bad idea.

I was looking at SVGeezy, a mini JavaScript plugin specifically for helping with SVG-as-img fallbacks. Of course, in order for it to work, it needs to do a feature detect. In the source code, it’s a simple a one liner:

supportsSvg: function() {
  return document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", "1.1");
}

I had never seen document.implementation.hasFeature ever before, so I asked around a bit, as it seemed a little too good to be true for something I’d never even heard of. Most documentation out there is pretty generic and suggest great browser support, making me even more skeptical.

The deal is: it’s pretty much useless. It almost always returns true for everything. Except, apparently, in the case of SVG-as-img, when it’s correct. As a skeptic, I went about creating a test to see if this was really true.

The first thing I did was check how Modernizr detects it, as the go-to source for feature detects. Important note here: Modernizr’s default SVG test (Modernizr.svg) is not testing SVG-as-img support, it’s testing SVG support as an <object> or <embed>. Just be aware of that when using it for fallbacks. Test the right thing (they have tests for all the ways you can use SVG).

They have a test specifically for SVG-as-img that was like this:

Modernizr.addAsyncTest(function () {
  var img = new Image();

  img.onerror = function () {
    addTest('svgasimg', false);
  };
  img.onload = function () {
    addTest('svgasimg', img.width == 1 && img.height == 1);
  };

  // 1px x 1px SVG; must be base64 or URI encoded for IE9... base64 is shorter
  img.src = 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMSIgaGVpZ2h0PSIxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPjwvc3ZnPg==';
});

This creates an new image element, injects a Data URI of a 1×1 SVG image then either waits for it to fail or load correctly.

Obviously different than the hasFeature test, so I created a Pen that showed the results of both methods. Then I tested in all kinds of different browsers. A mixture of those which are known to support SVG-as-img and those that do not. In all cases, the results were identical. Weird, but pretty cool!

The original Modernizr test is what they call an “async” test, meaning it relies upon callback functions to give an answer. Modernizr generally prefers “sync” tests in which as soon as the test is defined it has the right answer.

So, after talking about it with the Modernizr team, it is now the default test for SVG-as-img. It’s not quite out in a release yet, so for now you’d have to just run it.

Modernizr.addTest('svgasimg', document.implementation.hasFeature('http://www.w3.org/TR/SVG11/feature#Image', '1.1'));

I’ll update this post (and the version we run on CodePen) as soon as it’s out.

Thanks to Patrick Kettner for overseeing it getting into Modernizr, Stu Cox for the feedback and OKing the replacement of his original method, Ben Howdle for knowing about the cool hasFeature() and using it in SVGeezy and Mike Taylor for verifying it’s usefulness.

Oh, and if you you detect the browser doesn’t support SVG-as-img, you’ll want to flip out the src for an image format that is supported. Probably the-same-image.png either automatically based on a naming convention or selectively based on a data-* attribute.

Side note regarding “http://”

Don’t be scared by the non-secure “http://” in the paramter string involved here. No HTTP Request is made, and it will not hurt an HTTPS site. In fact, if you change it, it will hurt you. Jim Coffey writes in:

If you instead specify ‘https’, then most browsers will cope, but IE will fail the test.