Grow your CSS skills. Land your dream job.

Test for Support of SVG as img

Published by Chris Coyier

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 1x1 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.

Comments

  1. Thanks for posting about this, Chris! I ran into this same issue a few weeks ago. As you probably saw, SVG’s in Safari 5.1 calculate the height really tall, so you get super tall SVG images.

    My hacky fix was to look at the height and if it was really tall, fallback to png.

    Glad to see this is coming to Modernizr!

  2. I have found this jQuery plugin from the Sidebar, seems very robust, I was thinking on using it for my own website: http://svgmagic.bitlabs.nl/

    • Yeah that’s pretty neat because the fallbacks are created for you instead of you having to handle that yourself. But it does that by making an Ajax call to their servers on every page load of a non-supporting browser, so be aware of that.

  3. For what it’s worth, this type of feature test is called “weak inference”. The old feature test had its downsides (being asynchronous and all) but it was more robust.

  4. Pongo Twisleton
    Permalink to comment#

    I first discovered document.implementation.hasFeaturea week ago when I looked through the Rafael.js source code. Even if you don’t use Rafael to create SVG, it’s an incredibly good reference for how to use SVG with older browsers.

  5. Permalink to comment#

    document.implementation.hasFeature came onto my radar recently while searching for a workaround to the fact that Modernizr.touch returns true in Chrome or Firefox on Windows 8 even if there’s no touchscreen on the device. This snippet, to the degree I was able to test it, seems to help determine pretty well that a device is touch-only:

    document.implementation && document.implementation.hasFeature('MouseEvent', '3.0')===false

  6. Jignesh
    Permalink to comment#

    I have one another problem with SVG Logo.

    In my windows PC SVG logo work fine with safari browser, but when i upload it on server then SVG logo not load in safari browser.
    anyone have solution?…….

  7. Permalink to comment#

    Be careful using SVG images in HTML emails. After I spent days converting my email templates into a more responsive email-client centric format and using svg images for my logo and social media header images, it appears gmails image proxy has no plans to support svg images. If anyone has info to the contrary, please do share.

    http://stackoverflow.com/questions/20815613/svg-images-blocked-by-gmail-proxy?lq=1

This comment thread is closed. If you have important information to share, you can always contact me.

*May or may not contain any actual "CSS" or "Tricks".