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.
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!
Ryan: I can’t say for sure, but the issue you are seeing might be the same as this: https://twitter.com/zachleat/status/251446429418127360
An easier workaround is to use max-height: 100%;
I have exactly the same experience in safari 5.1. The max-height trick doesn’t work for me, although the img (svg container) becomes a bit shorter. The width is doing fine.
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.
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.
I specifically brought that up – but the team thought it was worth it to make the test sync. I agree, since hasFeature will likely return true forever and browser will support SVG in this way forever it probably will never be wrong.
I first discovered
document.implementation.hasFeature
a 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.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
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?…….
If your web server is using Microsoft IIS, it’s possible that it’s missing the MIME type for an SVG file – http://www.iis.net/learn/manage/managing-your-configuration-settings/adding-ie-9-mime-types-to-iis
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